-
Notifications
You must be signed in to change notification settings - Fork 376
[Instrumentation.Kusto] Add instrumentor for Azure Kusto #3591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e652e34
851079c
222f964
84eb6b3
4cddfea
786ad66
0462f33
4056495
cef4a17
b421e46
b4b64a2
71b7629
b87fe93
6b0e908
6bfd45d
229dafb
c64ee82
1514528
84c085e
d649f86
0090c35
12fad87
067f0e6
42697db
bfb8eca
3a97216
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -82,6 +82,9 @@ | |||
| <PackageVersion Include="Confluent.Kafka" Version="[2.4.0,)" /> | ||||
| <PackageVersion Include="Grpc.Core.Api" Version="[2.46.6,)" /> | ||||
| <PackageVersion Include="InfluxDB.Client" Version="[4.18.0,)" /> | ||||
| <PackageVersion Include="Microsoft.Azure.Kusto.Cloud.Platform" Version="[14.0.3,)" /> | ||||
| <PackageVersion Include="Microsoft.Azure.Kusto.Data" Version="14.0.3" /> | ||||
| <PackageVersion Include="Microsoft.Azure.Kusto.Language" Version="[12.3.1,)" /> | ||||
| <PackageVersion Include="Microsoft.ServiceFabric.Actors" Version="[7.1.2448,)" /> | ||||
| <PackageVersion Include="Microsoft.ServiceFabric.Services.Remoting" Version="[7.1.2448,)" /> | ||||
| <PackageVersion Include="Quartz" Version="[3.6.3,)" /> | ||||
|
|
@@ -122,9 +125,11 @@ | |||
| <PackageVersion Include="Microsoft.Data.SqlClient" Version="7.0.0" /> | ||||
| <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.25" /> | ||||
| <PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.25" /> | ||||
|
|
||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> | ||||
| <PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> | ||||
| <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" /> | ||||
| <PackageVersion Include="Microsoft.VisualStudio.DiagnosticsHub.BenchmarkDotNetDiagnosers" Version="18.3.36714.1" /> | ||||
| <PackageVersion Include="Microsoft.Web.Xdt" Version="3.2.5" /> | ||||
| <PackageVersion Include="MinVer" Version="7.0.0" /> | ||||
| <PackageVersion Include="MessagePack" Version="3.1.4" /> | ||||
|
|
@@ -140,9 +145,11 @@ | |||
| <!-- These WCF dependencies are pinned until we drop support for net8.0 and net9.0 --> | ||||
| <PackageVersion Include="System.ServiceModel.Http" Version="[8.1.2,)" /> | ||||
| <PackageVersion Include="System.ServiceModel.NetTcp" Version="[8.1.2,)" /> | ||||
| <PackageVersion Include="Testcontainers.Kusto" Version="4.11.0" /> | ||||
| <PackageVersion Include="Testcontainers.MsSql" Version="4.11.0" /> | ||||
| <PackageVersion Include="Testcontainers.MySql" Version="4.11.0" /> | ||||
| <PackageVersion Include="Testcontainers.PostgreSql" Version="4.11.0" /> | ||||
| <PackageVersion Include="Verify.Xunit" Version="31.4.3" /> | ||||
| <PackageVersion Include="xunit" Version="2.9.3" /> | ||||
| <PackageVersion Include="xunit.runner.visualstudio" Version="[2.8.2,)" /> | ||||
| <PackageVersion Include="Xunit.SkippableFact" Version="1.5.61" /> | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #nullable enable | ||
| OpenTelemetry.Metrics.KustoMeterInstrumentationOptions | ||
| OpenTelemetry.Metrics.KustoMeterInstrumentationOptions.KustoMeterInstrumentationOptions() -> void | ||
| OpenTelemetry.Metrics.KustoMeterInstrumentationOptions.RecordQuerySummary.get -> bool | ||
| OpenTelemetry.Metrics.KustoMeterInstrumentationOptions.RecordQuerySummary.set -> void | ||
| OpenTelemetry.Metrics.KustoMeterInstrumentationOptions.RecordQueryText.get -> bool | ||
| OpenTelemetry.Metrics.KustoMeterInstrumentationOptions.RecordQueryText.set -> void | ||
| OpenTelemetry.Metrics.MeterProviderBuilderExtensions | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.Enrich.get -> System.Action<System.Diagnostics.Activity!, Kusto.Cloud.Platform.Utils.TraceRecord!>? | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.Enrich.set -> void | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.KustoTraceInstrumentationOptions() -> void | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.RecordQuerySummary.get -> bool | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.RecordQuerySummary.set -> void | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.RecordQueryText.get -> bool | ||
| OpenTelemetry.Trace.KustoTraceInstrumentationOptions.RecordQueryText.set -> void | ||
| OpenTelemetry.Trace.TracerProviderBuilderExtensions | ||
| static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddKustoInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder) -> OpenTelemetry.Metrics.MeterProviderBuilder! | ||
| static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddKustoInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder, System.Action<OpenTelemetry.Metrics.KustoMeterInstrumentationOptions!>? configureKustoMeterInstrumentationOptions) -> OpenTelemetry.Metrics.MeterProviderBuilder! | ||
| static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddKustoInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder) -> OpenTelemetry.Trace.TracerProviderBuilder! | ||
| static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddKustoInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, System.Action<OpenTelemetry.Trace.KustoTraceInstrumentationOptions!>? configureKustoTraceInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder! |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,4 +2,5 @@ | |||||||
|
|
||||||||
| ## Unreleased | ||||||||
|
|
||||||||
| For more details, please refer to the [README](README.md). | ||||||||
| * Initial implementation. | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| ([#3591](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3591)) | ||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // Copyright The OpenTelemetry Authors | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace OpenTelemetry.Instrumentation.Kusto.Implementation; | ||
|
|
||
| /// <summary> | ||
| /// Provides extension methods for <see cref="InstrumentationHandleManager" />. | ||
| /// </summary> | ||
| internal static class InstrumentationHandleManagerExtensions | ||
| { | ||
| /// <summary> | ||
| /// Returns <see langword="true"/> if tracing is active (i.e., there is at least one tracing handle); otherwise, <see langword="false"/>. | ||
| /// </summary> | ||
| /// <param name="handleManager"> | ||
| /// The <see cref="InstrumentationHandleManager"/> to check for active tracing handles. | ||
| /// </param> | ||
| /// <returns><see langword="true"/> if tracing is active; otherwise, <see langword="false"/>.</returns> | ||
| public static bool IsTracingActive(this InstrumentationHandleManager handleManager) => handleManager.TracingHandles > 0; | ||
|
|
||
| /// <summary> | ||
| /// Returns <see langword="true"/> if metrics is active (i.e., there is at least one metrics handle); otherwise, <see langword="false"/>. | ||
| /// </summary> | ||
| /// <param name="handleManager"> | ||
| /// The <see cref="InstrumentationHandleManager"/> to check for active metrics handles. | ||
| /// </param> | ||
| /// <returns><see langword="true"/> if metrics is active; otherwise, <see langword="false"/>.</returns> | ||
| public static bool IsMetricsActive(this InstrumentationHandleManager handleManager) => handleManager.MetricHandles > 0; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copyright The OpenTelemetry Authors | ||||||||||||||||||||||||||||||||||||||||||||||||||
| // SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Diagnostics; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Diagnostics.Metrics; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Reflection; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using OpenTelemetry.Internal; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace OpenTelemetry.Instrumentation.Kusto.Implementation; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Helper class to hold common properties used by Kusto instrumentation. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| internal static class KustoActivitySourceHelper | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this contains activities and meters, I would give it a different name. |
||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| public const string DbSystem = "azure.kusto"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Conider |
||||||||||||||||||||||||||||||||||||||||||||||||||
| public const string ClientRequestIdTagKey = $"{DbSystem}.client_request_id"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly Assembly Assembly = typeof(KustoActivitySourceHelper).Assembly; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly AssemblyName AssemblyName = Assembly.GetName(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly string PackageVersion = Assembly.GetPackageVersion(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly string ActivitySourceName = AssemblyName.Name!; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly ActivitySource ActivitySource = new(ActivitySourceName, PackageVersion); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also include a schema URL like we do here: opentelemetry-dotnet-contrib/src/OpenTelemetry.Instrumentation.AspNet/AspNetInstrumentation.cs Lines 49 to 72 in d1717a8
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly string MeterName = AssemblyName.Name!; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly Meter Meter = new(MeterName, PackageVersion); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly Histogram<double> OperationDurationHistogram = Meter.CreateHistogram( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "db.client.operation.duration", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| unit: "s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| advice: new InstrumentAdvice<double>() { HistogramBucketBoundaries = [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10] }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "Duration of database client operations"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Copyright The OpenTelemetry Authors | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| using Kusto.Cloud.Platform.Utils; | ||
| using OpenTelemetry.Metrics; | ||
| using OpenTelemetry.Trace; | ||
|
|
||
| namespace OpenTelemetry.Instrumentation.Kusto.Implementation; | ||
|
|
||
| /// <summary> | ||
| /// Class to hold the singleton instances used for Kusto instrumentation. | ||
| /// </summary> | ||
| internal static class KustoInstrumentation | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to design this without needing statics? Then the tests can be simpler too. |
||
| { | ||
| private static readonly Lazy<ITraceListener> Listener = new(() => | ||
| { | ||
| Environment.SetEnvironmentVariable("KUSTO_DATA_TRACE_REQUEST_BODY", "1"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure we should be changing process env vars internally. If this is some internal implementation detail like how the Azure SDKs need (needed?) an opt-in to emit OTel metrics, I would instead document that the user is required to set that themselves. It's also messy for tests as it changes the test environment. |
||
|
|
||
| var listener = new KustoTraceRecordListener(); | ||
| TraceSourceManager.AddTraceListener(listener, startupDone: true); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this do exactly? |
||
|
|
||
| return listener; | ||
| }); | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the post-configured trace options for Kusto instrumentation. | ||
| /// </summary> | ||
| public static KustoTraceInstrumentationOptions TraceOptions { get; set; } = new(); | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the post-configured meter options for Kusto instrumentation. | ||
| /// </summary> | ||
| public static KustoMeterInstrumentationOptions MeterOptions { get; set; } = new(); | ||
|
|
||
| /// <summary> | ||
| /// Gets the <see cref="InstrumentationHandleManager"/> that tracks if there are any active listeners for <see cref="KustoTraceRecordListener"/>. | ||
| /// </summary> | ||
| public static InstrumentationHandleManager HandleManager { get; } = new(); | ||
|
|
||
| /// <summary> | ||
| /// Initializes the Kusto instrumentation by ensuring the listener is created and registered with the client library. | ||
| /// </summary> | ||
| public static void Initialize() => _ = Listener.Value; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||
| // Copyright The OpenTelemetry Authors | ||||||
| // SPDX-License-Identifier: Apache-2.0 | ||||||
|
|
||||||
| using System.Diagnostics.Tracing; | ||||||
| using OpenTelemetry.Internal; | ||||||
|
|
||||||
| namespace OpenTelemetry.Instrumentation.Kusto.Implementation; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// EventSource for Kusto instrumentation. | ||||||
| /// </summary> | ||||||
| [EventSource(Name = "OpenTelemetry-Instrumentation-Kusto")] | ||||||
| internal sealed class KustoInstrumentationEventSource : EventSource | ||||||
| { | ||||||
| public static KustoInstrumentationEventSource Log { get; } = new(); | ||||||
|
|
||||||
| [NonEvent] | ||||||
| public void EnrichmentException(Exception ex) | ||||||
| { | ||||||
| if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) | ||||||
| { | ||||||
| this.EnrichmentException(ex.ToInvariantString()); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| [Event(1, Message = "Enrichment exception: {0}", Level = EventLevel.Error)] | ||||||
| public void EnrichmentException(string exception) => this.WriteEvent(1, exception); | ||||||
|
|
||||||
| [Event(2, Message = "Trace record payload is NULL or has NULL message, record will not be processed.", Level = EventLevel.Warning)] | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| public void NullPayload() => this.WriteEvent(2); | ||||||
|
|
||||||
| [Event(3, Message = "Failed to find context for activity ID '{0}', operation data will not be recorded.", Level = EventLevel.Warning)] | ||||||
| public void ContextNotFound(string activityId) => this.WriteEvent(3, activityId); | ||||||
|
|
||||||
| [NonEvent] | ||||||
| public void UnknownErrorProcessingTraceRecord(Exception ex) | ||||||
| { | ||||||
| if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) | ||||||
| { | ||||||
| this.UnknownErrorProcessingTraceRecord(ex.ToInvariantString()); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| [Event(4, Message = "Unknown error processing trace record, Exception: {0}", Level = EventLevel.Error)] | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| public void UnknownErrorProcessingTraceRecord(string exception) => this.WriteEvent(4, exception); | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some other settings we should add for Verify, such as changes to
.editorconfigsettings. See here for some of the missing parts.