Skip to content

Commit

Permalink
Add initial MySql.Data instrumentation for the affected 8.0.33 nuget …
Browse files Browse the repository at this point in the history
…package where source instrumentation does not work
  • Loading branch information
zacharycmontoya committed Jun 21, 2023
1 parent c445ff1 commit 985f7e6
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// <copyright file="ExecuteReaderAsyncIntegration.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

#if NET6_0_OR_GREATER

using System.Data;
using System.Threading;
using OpenTelemetry.AutoInstrumentation.CallTarget;
using OpenTelemetry.AutoInstrumentation.Util;

namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MySqlData;

/// <summary>
/// MySql.Data.MySqlClient.MySqlCommand.ExecuteReaderAsyncIntegration calltarget instrumentation
/// </summary>
[InstrumentMethod(
assemblyName: "MySql.Data",
typeName: "MySql.Data.MySqlClient.MySqlCommand",
methodName: "ExecuteReaderAsync",
returnTypeName: "System.Threading.Tasks.Task`1<MySql.Data.MySqlClient.MySqlDataReader>",
parameterTypeNames: new[] { "System.Data.CommandBehavior", ClrNames.Bool, ClrNames.CancellationToken },
minimumVersion: "8.0.33",
maximumVersion: "8.65535.65535",
integrationName: "MySqlData",
type: InstrumentationType.Trace)]
public static class ExecuteReaderAsyncIntegration
{
/// <summary>
/// OnMethodBegin callback
/// </summary>
/// <typeparam name="TTarget">Type of the target</typeparam>
/// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
/// <param name="commandBehavior">The provided CommandBehavior value.</param>
/// <param name="execAsync">Indicates whether to run the query asynchronously</param>
/// <param name="cancellationToken">The provided CancellationToken value.</param>
/// <returns>CallTarget state value</returns>
internal static CallTargetState OnMethodBegin<TTarget>(TTarget instance, CommandBehavior commandBehavior, bool execAsync, CancellationToken cancellationToken)
where TTarget : IMySqlCommand
{
return new CallTargetState(activity: MySqlDataCommon.CreateActivity(instance), state: instance!);
}

/// <summary>
/// OnAsyncMethodEnd callback
/// </summary>
/// <typeparam name="TTarget">Type of the target</typeparam>
/// <typeparam name="TResult">Type of the result value</typeparam>
/// <param name="instance">Instance value, aka `this` of the instrumented method.</param>
/// <param name="result">The result value.</param>
/// <param name="exception">Exception instance in case the original code threw an exception.</param>
/// <param name="state">Calltarget state value</param>
/// <returns>A response value, in an async scenario will be T of Task of T</returns>
internal static TResult OnAsyncMethodEnd<TTarget, TResult>(TTarget instance, TResult result, Exception? exception, in CallTargetState state)
{
var activity = state.Activity;
if (activity is null)
{
return result;
}

try
{
if (exception != null)
{
activity.SetException(exception);
}
}
finally
{
activity.Dispose();
}

return result;
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// <copyright file="IMySqlCommand.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System.Data;

namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MySqlData;
internal interface IMySqlCommand
{
IMySqlConnection? SqlConnection { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// <copyright file="IMySqlConnection.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MySqlData;

internal interface IMySqlConnection
{
IMySqlConnectionStringBuilder Settings { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// <copyright file="IMySqlConnectionStringBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MySqlData;

internal interface IMySqlConnectionStringBuilder
{
string Database { get; }

uint Port { get; }

string Server { get; }

string UserID { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// <copyright file="MySqlDataCommon.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System.Data;
using System.Diagnostics;

namespace OpenTelemetry.AutoInstrumentation.Instrumentations.MySqlData;

internal class MySqlDataCommon
{
internal const string DbName = "db.name";
internal const string DbSystem = "db.system";
internal const string DbStatement = "db.statement";
internal const string DbUser = "db.user";

internal const string NetPeerIp = "net.peer.ip";
internal const string NetPeerPort = "net.peer.port";
internal const string NetPeerName = "net.peer.name";

internal const string PeerService = "peer.service";

internal const string MysqlDatabaseSystemName = "mysql";
internal static readonly ActivitySource ActivitySource = new ActivitySource(
"OpenTelemetry.Instrumentation.MySqlData", Constants.Tracer.Version); // In the library, it uses the version of the instrumentation library, e.g. "1.0.0.7"

internal static readonly IEnumerable<KeyValuePair<string, object?>> CreationTags = new[]
{
new KeyValuePair<string, object?>(DbSystem, MysqlDatabaseSystemName),
};

internal static Activity? CreateActivity<TCommand>(TCommand command)
where TCommand : IMySqlCommand
{
var activity = ActivitySource.StartActivity("OpenTelemetry.Instrumentation.MySqlData.Execute", ActivityKind.Client, Activity.Current?.Context ?? default, CreationTags);
if (activity is null)
{
return null;
}

if (activity.IsAllDataRequested)
{
// Figure out how to get the options, if possible
/*
if (this.options.SetDbStatement)
{
activity.SetTag(DbStatement, command.CommandText);
}
*/

if (command.SqlConnection?.Settings is not null)
{
activity.DisplayName = command.SqlConnection.Settings.Database;
activity.SetTag(DbName, command.SqlConnection.Settings.Database);

AddConnectionLevelDetailsToActivity(command.SqlConnection.Settings, activity);
}
}

return activity;
}

internal static void StopActivity(Activity activity)
{
if (activity.Source != ActivitySource)
{
return;
}

activity.Stop();
}

private static void AddConnectionLevelDetailsToActivity(IMySqlConnectionStringBuilder dataSource, Activity activity)
{
// Figure out how to get the options, if possible
/*
if (!this.options.EnableConnectionLevelAttributes)
{
activity.SetTag(PeerService, dataSource.Server);
}
else
{
var uriHostNameType = Uri.CheckHostName(dataSource.Server);
if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
activity.SetTag(NetPeerIp, dataSource.Server);
}
else
{
activity.SetTag(NetPeerName, dataSource.Server);
}
activity.SetTag(NetPeerPort, dataSource.Port);
activity.SetTag(DbUser, dataSource.UserID);
}
*/
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MySql.Data" VersionOverride="$(LibraryVersion)" />
<!-- Manually edited the csproj to test the new project -->
<!-- <PackageReference Include="MySql.Data" VersionOverride="$(LibraryVersion)" /> -->
<PackageReference Include="MySql.Data" VersionOverride="8.0.33" />
</ItemGroup>

</Project>

0 comments on commit 985f7e6

Please sign in to comment.