From 9c19f442dbd20cb5cdbcd4815ae7291180080177 Mon Sep 17 00:00:00 2001 From: tyler jago Date: Thu, 26 May 2022 10:04:27 -0600 Subject: [PATCH 1/5] Addjaeger (#7) * added jaeger progagator with tests * updated changelog * moved comment to unreleased --- .../.publicApi/net462/PublicAPI.Unshipped.txt | 5 + .../netstandard2.0/PublicAPI.Unshipped.txt | 5 + .../CHANGELOG.md | 2 + .../JaegerPropagator.cs | 180 ++++++++++++++ .../JaegerPropagatorTest.cs | 235 ++++++++++++++++++ 5 files changed, 427 insertions(+) create mode 100644 src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs create mode 100644 test/OpenTelemetry.Extensions.Propagators.Tests/JaegerPropagatorTest.cs diff --git a/src/OpenTelemetry.Extensions.Propagators/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Extensions.Propagators/.publicApi/net462/PublicAPI.Unshipped.txt index e69de29bb2d..ee1db2f0d31 100644 --- a/src/OpenTelemetry.Extensions.Propagators/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Extensions.Propagators/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,5 @@ +OpenTelemetry.Extensions.Propagators.JaegerPropagator +OpenTelemetry.Extensions.Propagators.JaegerPropagator.JaegerPropagator() -> void +override OpenTelemetry.Extensions.Propagators.JaegerPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +override OpenTelemetry.Extensions.Propagators.JaegerPropagator.Fields.get -> System.Collections.Generic.ISet +override OpenTelemetry.Extensions.Propagators.JaegerPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void diff --git a/src/OpenTelemetry.Extensions.Propagators/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Extensions.Propagators/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index e69de29bb2d..ee1db2f0d31 100644 --- a/src/OpenTelemetry.Extensions.Propagators/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Extensions.Propagators/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1,5 @@ +OpenTelemetry.Extensions.Propagators.JaegerPropagator +OpenTelemetry.Extensions.Propagators.JaegerPropagator.JaegerPropagator() -> void +override OpenTelemetry.Extensions.Propagators.JaegerPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +override OpenTelemetry.Extensions.Propagators.JaegerPropagator.Fields.get -> System.Collections.Generic.ISet +override OpenTelemetry.Extensions.Propagators.JaegerPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void diff --git a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md index bf0af07b4ae..c9dfac54689 100644 --- a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md @@ -4,3 +4,5 @@ * Initial release. This has been ported as is from [OpenTelemetry.Api](../OpenTelemetry.Api/README.md) package. + +* added jaegerpropagator for issue [1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881) diff --git a/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs b/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs new file mode 100644 index 00000000000..b175a36ce57 --- /dev/null +++ b/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs @@ -0,0 +1,180 @@ +// +// 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. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using OpenTelemetry.Context.Propagation; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Extensions.Propagators; + +/// +/// A text map propagator for Jaeger trace context. See https://www.jaegertracing.io/docs/next-release/client-libraries/#propagation-format. +/// +public class JaegerPropagator : TextMapPropagator +{ + internal const string JaegerHeader = "uber-trace-id"; + internal const string JaegerDelimiter = ":"; + internal const string JaegerDelimiterEncoded = "%3A"; // while the spec defines the delimiter as a ':', some clients will url encode headers. + internal const string SampledValue = "1"; + + internal static readonly string[] JaegerDelimiters = { JaegerDelimiter, JaegerDelimiterEncoded }; + + private static readonly int TraceId128BitLength = "0af7651916cd43dd8448eb211c80319c".Length; + private static readonly int SpanIdLength = "00f067aa0ba902b7".Length; + + /// + public override ISet Fields => new HashSet { JaegerHeader }; + + /// + public override PropagationContext Extract(PropagationContext context, T carrier, Func> getter) + { + if (context.ActivityContext.IsValid()) + { + // If a valid context has already been extracted, perform a noop. + return context; + } + + if (carrier == null) + { + OpenTelemetryApiEventSource.Log.FailedToExtractActivityContext(nameof(JaegerPropagator), "null carrier"); + return context; + } + + if (getter == null) + { + OpenTelemetryApiEventSource.Log.FailedToExtractActivityContext(nameof(JaegerPropagator), "null getter"); + return context; + } + + try + { + var jaegerHeaderCollection = getter(carrier, JaegerHeader); + var jaegerHeader = jaegerHeaderCollection?.First(); + + if (string.IsNullOrWhiteSpace(jaegerHeader)) + { + return context; + } + + var jaegerHeaderParsed = TryExtractTraceContext(jaegerHeader, out var traceId, out var spanId, out var traceOptions); + + if (!jaegerHeaderParsed) + { + return context; + } + + return new PropagationContext( + new ActivityContext(traceId, spanId, traceOptions, isRemote: true), + context.Baggage); + } + catch (Exception ex) + { + OpenTelemetryApiEventSource.Log.ActivityContextExtractException(nameof(JaegerPropagator), ex); + } + + return context; + } + + /// + public override void Inject(PropagationContext context, T carrier, Action setter) + { + // from https://www.jaegertracing.io/docs/next-release/client-libraries/#propagation-format + // parent id is optional and deprecated, will not attempt to set it. + // 128 bit uber-trace-id=e0ad975be108cd107990683f59cda9e6:e422f3fe664f6342:0:1 + const string defaultParentSpanId = "0"; + + if (context.ActivityContext.TraceId == default || context.ActivityContext.SpanId == default) + { + OpenTelemetryApiEventSource.Log.FailedToInjectActivityContext(nameof(JaegerPropagator), "Invalid context"); + return; + } + + if (carrier == null) + { + OpenTelemetryApiEventSource.Log.FailedToInjectActivityContext(nameof(JaegerPropagator), "null carrier"); + return; + } + + if (setter == null) + { + OpenTelemetryApiEventSource.Log.FailedToInjectActivityContext(nameof(JaegerPropagator), "null setter"); + return; + } + + var flags = (context.ActivityContext.TraceFlags & ActivityTraceFlags.Recorded) != 0 ? "1" : "0"; + + var jaegerTrace = string.Join( + JaegerDelimiter, + context.ActivityContext.TraceId.ToHexString(), + context.ActivityContext.SpanId.ToHexString(), + defaultParentSpanId, + flags); + + setter(carrier, JaegerHeader, jaegerTrace); + } + + internal static bool TryExtractTraceContext(string jaegerHeader, out ActivityTraceId traceId, out ActivitySpanId spanId, out ActivityTraceFlags traceOptions) + { + // from https://www.jaegertracing.io/docs/next-release/client-libraries/#propagation-format + // parent id is optional and deprecated. will not attempt to store it. + // 128 bit uber-trace-id=e0ad975be108cd107990683f59cda9e6:e422f3fe664f6342:0:1 + // 128 bit with encoded delimiter uber-trace-id=e0ad975be108cd107990683f59cda9e6%3Ae422f3fe664f6342%3A0%3A1 + // 64 bit uber-trace-id=7990683f59cda9e6:e422f3fe664f6342:0:1 + // 64 bit with encoded delimiter uber-trace-id=7990683f59cda9e6%3Ae422f3fe664f6342%3A0%3A1 + + traceId = default; + spanId = default; + traceOptions = ActivityTraceFlags.None; + + if (string.IsNullOrWhiteSpace(jaegerHeader)) + { + return false; + } + + var traceComponents = jaegerHeader.Split(JaegerDelimiters, StringSplitOptions.RemoveEmptyEntries); + if (traceComponents.Length != 4) + { + return false; + } + + var traceIdStr = traceComponents[0]; + if (traceIdStr.Length < TraceId128BitLength) + { + traceIdStr = traceIdStr.PadLeft(TraceId128BitLength, '0'); + } + + traceId = ActivityTraceId.CreateFromString(traceIdStr.AsSpan()); + + var spanIdStr = traceComponents[1]; + if (spanIdStr.Length < SpanIdLength) + { + spanIdStr = spanIdStr.PadLeft(SpanIdLength, '0'); + } + + spanId = ActivitySpanId.CreateFromString(spanIdStr.AsSpan()); + + var traceFlagsStr = traceComponents[3]; + if (SampledValue.Equals(traceFlagsStr)) + { + traceOptions |= ActivityTraceFlags.Recorded; + } + + return true; + } +} diff --git a/test/OpenTelemetry.Extensions.Propagators.Tests/JaegerPropagatorTest.cs b/test/OpenTelemetry.Extensions.Propagators.Tests/JaegerPropagatorTest.cs new file mode 100644 index 00000000000..05f174561b1 --- /dev/null +++ b/test/OpenTelemetry.Extensions.Propagators.Tests/JaegerPropagatorTest.cs @@ -0,0 +1,235 @@ +// +// 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. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using OpenTelemetry.Context.Propagation; +using Xunit; + +namespace OpenTelemetry.Extensions.Propagators.Tests +{ + public class JaegerPropagatorTest + { + private const string JaegerHeader = "uber-trace-id"; + private const string JaegerDelimiter = ":"; + private const string JaegerDelimiterEncoded = "%3A"; + + private const string TraceId = "0007651916cd43dd8448eb211c803177"; + private const string TraceIdShort = "7651916cd43dd8448eb211c803177"; + private const string SpanId = "0007c989f9791877"; + private const string SpanIdShort = "7c989f9791877"; + private const string ParentSpanId = "0"; + private const string FlagSampled = "1"; + private const string FlagNotSampled = "0"; + + private static readonly Func, string, IEnumerable> Getter = (headers, name) => + { + if (headers.TryGetValue(name, out var value)) + { + return value; + } + + return Array.Empty(); + }; + + private static readonly Action, string, string> Setter = (carrier, name, value) => + { + carrier[name] = value; + }; + + [Fact] + public void ExtractReturnsOriginalContextIfContextIsAlreadyValid() + { + // arrange + var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan()); + var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan()); + var propagationContext = new PropagationContext( + new ActivityContext(traceId, spanId, ActivityTraceFlags.Recorded, isRemote: true), + default); + + var headers = new Dictionary(); + + // act + var result = new JaegerPropagator().Extract(propagationContext, headers, Getter); + + // assert + Assert.Equal(propagationContext, result); + } + + [Fact] + public void ExtractReturnsOriginalContextIfCarrierIsNull() + { + // arrange + var propagationContext = default(PropagationContext); + + // act + var result = new JaegerPropagator().Extract(propagationContext, null, Getter!); + + // assert + Assert.Equal(propagationContext, result); + } + + [Fact] + public void ExtractReturnsOriginalContextIfGetterIsNull() + { + // arrange + var propagationContext = default(PropagationContext); + + var headers = new Dictionary(); + + // act + var result = new JaegerPropagator().Extract(propagationContext, headers, null); + + // assert + Assert.Equal(propagationContext, result); + } + + [Theory] + [InlineData("", SpanId, ParentSpanId, FlagSampled, JaegerDelimiter)] + [InlineData(TraceId, "", ParentSpanId, FlagSampled, JaegerDelimiter)] + [InlineData(TraceId, SpanId, "", FlagSampled, JaegerDelimiter)] + [InlineData(TraceId, SpanId, ParentSpanId, "", JaegerDelimiter)] + [InlineData(TraceId, SpanId, ParentSpanId, FlagSampled, "")] + [InlineData("invalid trace id", SpanId, ParentSpanId, FlagSampled, JaegerDelimiter)] + [InlineData(TraceId, "invalid span id", ParentSpanId, FlagSampled, JaegerDelimiter)] + [InlineData(TraceId, SpanId, $"too many {JaegerDelimiter} records", FlagSampled, JaegerDelimiter)] + public void ExtractReturnsOriginalContextIfHeaderIsNotValid(string traceId, string spanId, string parentSpanId, string flags, string delimiter) + { + // arrange + var propagationContext = default(PropagationContext); + + var formattedHeader = string.Join( + delimiter, + traceId, + spanId, + parentSpanId, + flags); + + var headers = new Dictionary { { JaegerHeader, new[] { formattedHeader } } }; + + // act + var result = new JaegerPropagator().Extract(propagationContext, headers, Getter); + + // assert + Assert.Equal(propagationContext, result); + } + + [Theory] + [InlineData(TraceId, SpanId, ParentSpanId, FlagSampled, JaegerDelimiter)] + [InlineData(TraceIdShort, SpanIdShort, ParentSpanId, FlagNotSampled, JaegerDelimiterEncoded)] + public void ExtractReturnsNewContextIfHeaderIsValid(string traceId, string spanId, string parentSpanId, string flags, string delimiter) + { + // arrange + var propagationContext = default(PropagationContext); + + var formattedHeader = string.Join( + delimiter, + traceId, + spanId, + parentSpanId, + flags); + + var headers = new Dictionary { { JaegerHeader, new[] { formattedHeader } } }; + + // act + var result = new JaegerPropagator().Extract(propagationContext, headers, Getter); + + // assert + Assert.Equal(traceId.PadLeft(TraceId.Length, '0'), result.ActivityContext.TraceId.ToString()); + Assert.Equal(spanId.PadLeft(SpanId.Length, '0'), result.ActivityContext.SpanId.ToString()); + Assert.Equal(flags == "1" ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None, result.ActivityContext.TraceFlags); + } + + [Fact] + public void InjectDoesNoopIfContextIsInvalid() + { + // arrange + var propagationContext = default(PropagationContext); + + var headers = new Dictionary(); + + // act + new JaegerPropagator().Inject(propagationContext, headers, Setter); + + // assert + Assert.Empty(headers); + } + + [Fact] + public void InjectDoesNoopIfCarrierIsNull() + { + // arrange + var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan()); + var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan()); + var propagationContext = new PropagationContext( + new ActivityContext(traceId, spanId, ActivityTraceFlags.Recorded, isRemote: true), + default); + + // act + new JaegerPropagator().Inject(propagationContext, null, Setter!); + + // assert + } + + [Fact] + public void InjectDoesNoopIfSetterIsNull() + { + // arrange + var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan()); + var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan()); + var propagationContext = new PropagationContext( + new ActivityContext(traceId, spanId, ActivityTraceFlags.Recorded, isRemote: true), + default); + + var headers = new Dictionary(); + + // act + new JaegerPropagator().Inject(propagationContext, headers, null); + + // assert + Assert.Empty(headers); + } + + [Theory] + [InlineData(FlagSampled)] + [InlineData(FlagNotSampled)] + public void InjectWillAddJaegerFormattedTraceToCarrier(string sampledFlag) + { + // arrange + var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan()); + var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan()); + var flags = sampledFlag == "1" ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None; + + var propagationContext = new PropagationContext(new ActivityContext(traceId, spanId, flags, isRemote: true), default); + + var expectedValue = string.Join( + JaegerDelimiter, + traceId, + spanId, + ParentSpanId, + sampledFlag); + + var headers = new Dictionary(); + + // act + new JaegerPropagator().Inject(propagationContext, headers, Setter); + + // assert + Assert.Single(headers); + Assert.Equal(expectedValue, headers[JaegerHeader]); + } + } +} From afd7a88b5f92a874fac20a0b04d6c03d0e3bae45 Mon Sep 17 00:00:00 2001 From: tyler jago Date: Mon, 6 Jun 2022 08:09:29 -0600 Subject: [PATCH 2/5] Update CHANGELOG.md nit from PR comments --- src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md index c9dfac54689..d89c0d3c8dd 100644 --- a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md @@ -5,4 +5,4 @@ * Initial release. This has been ported as is from [OpenTelemetry.Api](../OpenTelemetry.Api/README.md) package. -* added jaegerpropagator for issue [1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881) +* Added JaegerPropagator ([1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881)) From 442c6a0c447018d75ddc9dd5ef241fe87cc5c327 Mon Sep 17 00:00:00 2001 From: tyler jago Date: Wed, 8 Jun 2022 07:16:23 -0600 Subject: [PATCH 3/5] Anotherrefresh (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactor string extensions (#3306) * fixing InMemoryExporter & Metrics bug. new class: MetricSnapshot. new ctor: InMemoryExporter(Func) (#3266) * Exporting tags consistently (#3281) * feat(tracing): deprecate use of B3 propagator class from API package - use Extensions.Propagators package instead (#3289) * Use TagTransformer for ConsoleExporter 💻 (#3311) * Add core tag prefix to OTLP logs project (#3316) * Add Extensions.Propagators to core (#3318) * Changelog update for 1.3.0-rc.1 release prep (#3320) * Adjust changelog to reflect actual date and package (#3327) * Update protos to 0.18.0 (#3321) Co-authored-by: Cijo Thomas * Propagation in case of remote parent (#3310) * Replace MOQ with InMemoryExporter in ASP.NET Core (#3328) * cleanup CI (#3332) * ConsoleMetricExporter to export all resource attributes (#3334) * Fix EventSource for B3Propagator (#3336) * Update changelog to prepare release (#3337) * Move public api to shipped (#3338) * Post release cleanups (#3340) * Fix NullReferenceException caught by SDK when metric has a tag with a null value (#3325) * Add isRemote check for context propagation (#3329) * Minor test fixes sln additions (#3341) * Update .sln file;Remove docker compose file for net5.0 (#3347) * Remove StackExchangeRedis Instrumenation (#3346) Co-authored-by: Cijo Thomas * fixed event source in jaegerpropagator after pulling latest Co-authored-by: Piotr Kiełkowicz Co-authored-by: Timothy Mothra Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> Co-authored-by: John Co-authored-by: Cijo Thomas Co-authored-by: Vishwesh Bankwar Co-authored-by: Reiley Yang Co-authored-by: Utkarsh Umesan Pillai --- .github/workflows/apicompatibility.yml | 2 +- .github/workflows/code-coverage.yml | 4 +- .github/workflows/docfx.yml | 4 +- .github/workflows/dotnet-format.yml | 4 +- .github/workflows/integration-md.yml | 8 - .github/workflows/integration.yml | 16 +- .github/workflows/linux-ci.yml | 4 +- .github/workflows/markdownlint.yml | 4 +- .github/workflows/sanitycheck.yml | 4 +- .github/workflows/windows-ci.yml | 4 +- OpenTelemetry.sln | 19 +- README.md | 1 - build/Common.nonprod.props | 1 - build/Common.props | 3 +- build/docker-compose.net5.0.yml | 8 - docs/trace/extending-the-sdk/README.md | 65 ++- examples/Console/Examples.Console.csproj | 2 - examples/Console/Program.cs | 10 +- examples/Console/TestRedis.cs | 111 ----- src/OpenTelemetry.Api/CHANGELOG.md | 13 + .../Context/Propagation/B3Propagator.cs | 10 + .../OpenTelemetry.Api.csproj | 8 +- .../CHANGELOG.md | 23 + .../ConsoleActivityExporter.cs | 25 +- .../ConsoleLogRecordExporter.cs | 22 +- .../ConsoleMetricExporter.cs | 14 +- .../ConsoleTagTransformer.cs | 40 ++ .../OpenTelemetry.Exporter.Console.csproj | 11 +- .../.publicApi/net462/PublicAPI.Shipped.txt | 14 + .../.publicApi/net462/PublicAPI.Unshipped.txt | 3 - .../netstandard2.0/PublicAPI.Shipped.txt | 14 + .../netstandard2.0/PublicAPI.Unshipped.txt | 3 - .../CHANGELOG.md | 12 + .../InMemoryExporter.cs | 12 +- .../InMemoryExporterMetricsExtensions.cs | 87 +++- .../MetricSnapshot.cs | 58 +++ .../OpenTelemetry.Exporter.InMemory.csproj | 12 - .../CHANGELOG.md | 27 ++ .../JaegerActivityExtensions.cs | 79 +--- .../Implementation/JaegerTagTransformer.cs | 52 +++ .../Implementation/Process.cs | 15 - .../JaegerExporter.cs | 11 +- .../JaegerExporterOptions.cs | 6 +- .../JaegerExporterProtocolParser.cs | 36 ++ .../OpenTelemetry.Exporter.Jaeger.csproj | 8 +- .../CHANGELOG.md | 4 + ...Exporter.OpenTelemetryProtocol.Logs.csproj | 1 + .../CHANGELOG.md | 8 + .../Implementation/ActivityExtensions.cs | 3 +- .../Implementation/LogRecordExtensions.cs | 11 +- .../Implementation/MetricItemExtensions.cs | 5 +- ...penTelemetryProtocolExporterEventSource.cs | 6 - .../Implementation/OtlpCommonExtensions.cs | 135 ------ .../Implementation/OtlpKeyValueTransformer.cs | 95 ++++ .../Implementation/ResourceExtensions.cs | 5 +- .../opentelemetry/proto/collector/README.md | 1 + .../collector/logs/v1/logs_service.proto | 3 - .../proto/metrics/v1/metrics.proto | 14 +- ...etry.Exporter.OpenTelemetryProtocol.csproj | 8 +- .../OtlpExportProtocolParser.cs | 37 ++ .../OtlpExporterOptions.cs | 5 +- .../OtlpExporterOptionsExtensions.cs | 8 - .../CHANGELOG.md | 4 + .../CHANGELOG.md | 4 + .../CHANGELOG.md | 27 ++ .../Implementation/ZipkinSpan.cs | 32 +- .../Implementation/ZipkinTagTransformer.cs | 40 ++ .../OpenTelemetry.Exporter.Zipkin.csproj | 7 +- .../CHANGELOG.md | 4 + .../B3Propagator.cs | 14 +- .../CHANGELOG.md | 11 + .../JaegerPropagator.cs | 12 +- ...penTelemetry.Extensions.Propagators.csproj | 11 +- .../OpenTelemetryPropagatorsEventSource.cs | 52 +++ .../README.md | 9 + .../CHANGELOG.md | 4 + .../CHANGELOG.md | 4 + .../CHANGELOG.md | 4 + .../CHANGELOG.md | 4 + .../CHANGELOG.md | 4 + .../CHANGELOG.md | 4 + .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 10 - .../netstandard2.0/PublicAPI.Shipped.txt | 0 .../netstandard2.0/PublicAPI.Unshipped.txt | 10 - .../AssemblyInfo.cs | 34 -- .../CHANGELOG.md | 109 ----- .../RedisProfilerEntryToActivityConverter.cs | 209 --------- ....Instrumentation.StackExchangeRedis.csproj | 22 - .../README.md | 137 ------ .../StackExchangeRedisCallsInstrumentation.cs | 151 ------- ...xchangeRedisCallsInstrumentationOptions.cs | 48 -- .../TracerProviderBuilderExtensions.cs | 90 ---- .../CHANGELOG.md | 4 + .../.publicApi/net462/PublicAPI.Shipped.txt | 213 ++++----- .../.publicApi/net462/PublicAPI.Unshipped.txt | 4 - .../netstandard2.0/PublicAPI.Shipped.txt | 213 ++++----- .../netstandard2.0/PublicAPI.Unshipped.txt | 4 - src/OpenTelemetry/AssemblyInfo.cs | 1 + src/OpenTelemetry/CHANGELOG.md | 17 + .../Internal/OpenTelemetrySdkEventSource.cs | 6 + .../Internal/TagAndValueTransformer.cs | 61 +++ src/OpenTelemetry/Internal/TagTransformer.cs | 138 ++++++ src/OpenTelemetry/Metrics/Tags.cs | 28 +- src/OpenTelemetry/OpenTelemetry.csproj | 6 - src/OpenTelemetry/Trace/TracerProviderSdk.cs | 12 +- .../JaegerActivityConversionTest.cs | 52 ++- ...s => JaegerExporterProtocolParserTests.cs} | 15 +- .../JaegerExporterTests.cs | 3 +- .../OtlpAttributeTests.cs | 43 +- .../OtlpExportProtocolParserTests.cs | 35 ++ .../OtlpExporterOptionsExtensionsTests.cs | 11 - .../ZipkinExporterTests.cs | 2 +- .../EventSourceTest.cs | 21 +- ...emetry.Extensions.Propagators.Tests.csproj | 5 + .../BasicTests.cs | 118 ++--- ...stsCollectionsIsAccordingToTheSpecTests.cs | 13 +- .../Dockerfile | 17 - ...isProfilerEntryToActivityConverterTests.cs | 181 -------- ...umentation.StackExchangeRedis.Tests.csproj | 31 -- ...kExchangeRedisCallsInstrumentationTests.cs | 417 ------------------ .../docker-compose.yml | 20 - .../Metrics/InMemoryExporterTests.cs | 33 +- .../Metrics/MetricAPITest.cs | 33 ++ .../Trace/BatchExportActivityProcessorTest.cs | 9 +- .../Trace/TracerProviderSdkTest.cs | 32 ++ 126 files changed, 1596 insertions(+), 2511 deletions(-) delete mode 100644 build/docker-compose.net5.0.yml delete mode 100644 examples/Console/TestRedis.cs create mode 100644 src/OpenTelemetry.Exporter.Console/ConsoleTagTransformer.cs create mode 100644 src/OpenTelemetry.Exporter.InMemory/MetricSnapshot.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagTransformer.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/JaegerExporterProtocolParser.cs delete mode 100644 src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpCommonExtensions.cs create mode 100644 src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpKeyValueTransformer.cs create mode 100644 src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExportProtocolParser.cs create mode 100644 src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagTransformer.cs create mode 100644 src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/AssemblyInfo.cs delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/CHANGELOG.md delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/Implementation/RedisProfilerEntryToActivityConverter.cs delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/OpenTelemetry.Instrumentation.StackExchangeRedis.csproj delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentation.cs delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentationOptions.cs delete mode 100644 src/OpenTelemetry.Instrumentation.StackExchangeRedis/TracerProviderBuilderExtensions.cs create mode 100644 src/OpenTelemetry/Internal/TagAndValueTransformer.cs create mode 100644 src/OpenTelemetry/Internal/TagTransformer.cs rename test/OpenTelemetry.Exporter.Jaeger.Tests/{JaegerExporterOptionsExtensionsTests.cs => JaegerExporterProtocolParserTests.cs} (54%) create mode 100644 test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExportProtocolParserTests.cs rename src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptionsExtensions.cs => test/OpenTelemetry.Extensions.Propagators.Tests/EventSourceTest.cs (56%) delete mode 100644 test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Dockerfile delete mode 100644 test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToActivityConverterTests.cs delete mode 100644 test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.csproj delete mode 100644 test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/StackExchangeRedisCallsInstrumentationTests.cs delete mode 100644 test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/docker-compose.yml diff --git a/.github/workflows/apicompatibility.yml b/.github/workflows/apicompatibility.yml index 9fb053744c8..937d296dee6 100644 --- a/.github/workflows/apicompatibility.yml +++ b/.github/workflows/apicompatibility.yml @@ -2,7 +2,7 @@ name: API Compatibility on: pull_request: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 42bcde11070..772d8e45a0b 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -2,11 +2,11 @@ name: Code Coverage on: push: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' pull_request: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' diff --git a/.github/workflows/docfx.yml b/.github/workflows/docfx.yml index 87c44c2a06f..b183f85311c 100644 --- a/.github/workflows/docfx.yml +++ b/.github/workflows/docfx.yml @@ -2,9 +2,9 @@ name: docfx on: push: - branches: [ main, metrics ] + branches: [ main ] pull_request: - branches: [ main, metrics ] + branches: [ main ] jobs: build: diff --git a/.github/workflows/dotnet-format.yml b/.github/workflows/dotnet-format.yml index e6c30761dbb..472fc5f6865 100644 --- a/.github/workflows/dotnet-format.yml +++ b/.github/workflows/dotnet-format.yml @@ -2,12 +2,12 @@ name: dotnet format on: push: - branches: [ main, metrics ] + branches: [ main ] paths: - '**.cs' - '.editorconfig' pull_request: - branches: [ main, metrics ] + branches: [ main ] paths: - '**.cs' - '.editorconfig' diff --git a/.github/workflows/integration-md.yml b/.github/workflows/integration-md.yml index c832bbf0657..aec19d81972 100644 --- a/.github/workflows/integration-md.yml +++ b/.github/workflows/integration-md.yml @@ -14,14 +14,6 @@ on: - '**.md' jobs: - redis-test: - runs-on: ubuntu-latest - strategy: - matrix: - version: [netcoreapp3.1,net6.0] - steps: - - run: 'echo "No build required"' - sql-test: runs-on: ubuntu-latest strategy: diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f82872602d2..b3d53770e77 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -2,27 +2,15 @@ name: Integration Tests on: push: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' pull_request: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' jobs: - redis-test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - version: [netcoreapp3.1,net6.0] - steps: - - uses: actions/checkout@v3 - - - name: Run redis docker-compose.integration - run: docker-compose --file=test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/docker-compose.yml --file=build/docker-compose.${{ matrix.version }}.yml --project-directory=. up --exit-code-from=tests --build - sql-test: runs-on: ubuntu-latest strategy: diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index 2768651bb2e..c8fec659ce7 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -2,11 +2,11 @@ name: Linux on: push: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' pull_request: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml index ab407428564..97f85f9e2b4 100644 --- a/.github/workflows/markdownlint.yml +++ b/.github/workflows/markdownlint.yml @@ -2,11 +2,11 @@ name: markdownlint on: push: - branches: [ main, metrics ] + branches: [ main ] paths: - '**.md' pull_request: - branches: [ main, metrics ] + branches: [ main ] paths: - '**.md' diff --git a/.github/workflows/sanitycheck.yml b/.github/workflows/sanitycheck.yml index a491644e238..a52563198e4 100644 --- a/.github/workflows/sanitycheck.yml +++ b/.github/workflows/sanitycheck.yml @@ -2,9 +2,9 @@ name: sanitycheck on: push: - branches: [ main, metrics ] + branches: [ main ] pull_request: - branches: [ main, metrics ] + branches: [ main ] jobs: misspell: diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 7427cc2dd2b..9996cd8ea83 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -2,11 +2,11 @@ name: Windows on: push: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' pull_request: - branches: [ main, metrics ] + branches: [ main ] paths-ignore: - '**.md' diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 8e14f86b9bc..e74cd272481 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -26,6 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7CB2F02E build\Common.props = build\Common.props build\debug.snk = build\debug.snk build\docfx.cmd = build\docfx.cmd + build\docker-compose.net6.0.yml = build\docker-compose.net6.0.yml build\docker-compose.netcoreapp3.1.yml = build\docker-compose.netcoreapp3.1.yml build\finalize-publicapi.ps1 = build\finalize-publicapi.ps1 build\opentelemetry-icon-color.png = build\opentelemetry-icon-color.png @@ -51,10 +52,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testdata", "testdata", "{77 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.AspNetCore.3.1", "test\TestApp.AspNetCore.3.1\TestApp.AspNetCore.3.1.csproj", "{F2F81E76-6A0E-466B-B673-EBBF1A9ED075}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.StackExchangeRedis", "src\OpenTelemetry.Instrumentation.StackExchangeRedis\OpenTelemetry.Instrumentation.StackExchangeRedis.csproj", "{6B681D72-D68A-44CC-8C75-53B9A322E6EC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.StackExchangeRedis.Tests", "test\OpenTelemetry.Instrumentation.StackExchangeRedis.Tests\OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.csproj", "{CA98AF29-0852-4ADD-A66B-7E96266EE7B7}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{E359BB2B-9AEC-497D-B321-7DF2450C3B8E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Jaeger", "src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj", "{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}" @@ -102,12 +99,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ .github\workflows\code-coverage.yml = .github\workflows\code-coverage.yml .github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml .github\workflows\docfx.yml = .github\workflows\docfx.yml + .github\workflows\dotnet-format-md.yml = .github\workflows\dotnet-format-md.yml .github\workflows\dotnet-format.yml = .github\workflows\dotnet-format.yml + .github\workflows\integration-md.yml = .github\workflows\integration-md.yml .github\workflows\integration.yml = .github\workflows\integration.yml + .github\workflows\linux-ci-md.yml = .github\workflows\linux-ci-md.yml .github\workflows\linux-ci.yml = .github\workflows\linux-ci.yml .github\workflows\markdownlint.yml = .github\workflows\markdownlint.yml .github\workflows\publish-packages-1.0.yml = .github\workflows\publish-packages-1.0.yml .github\workflows\sanitycheck.yml = .github\workflows\sanitycheck.yml + .github\workflows\windows-ci-md.yml = .github\workflows\windows-ci-md.yml .github\workflows\windows-ci.yml = .github\workflows\windows-ci.yml EndProjectSection EndProject @@ -233,7 +234,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Pr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Propagators.Tests", "test\OpenTelemetry.Extensions.Propagators.Tests\OpenTelemetry.Extensions.Propagators.Tests.csproj", "{476D804B-BFEC-4D34-814C-DFFD97109989}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "correlation", "docs\logs\correlation\correlation.csproj", "{9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "correlation", "docs\logs\correlation\correlation.csproj", "{9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -269,14 +270,6 @@ Global {F2F81E76-6A0E-466B-B673-EBBF1A9ED075}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2F81E76-6A0E-466B-B673-EBBF1A9ED075}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2F81E76-6A0E-466B-B673-EBBF1A9ED075}.Release|Any CPU.Build.0 = Release|Any CPU - {6B681D72-D68A-44CC-8C75-53B9A322E6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B681D72-D68A-44CC-8C75-53B9A322E6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B681D72-D68A-44CC-8C75-53B9A322E6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B681D72-D68A-44CC-8C75-53B9A322E6EC}.Release|Any CPU.Build.0 = Release|Any CPU - {CA98AF29-0852-4ADD-A66B-7E96266EE7B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA98AF29-0852-4ADD-A66B-7E96266EE7B7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA98AF29-0852-4ADD-A66B-7E96266EE7B7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA98AF29-0852-4ADD-A66B-7E96266EE7B7}.Release|Any CPU.Build.0 = Release|Any CPU {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/README.md b/README.md index fb134bf13ff..b7ab73708a0 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,6 @@ libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/ma * [ASP.NET Core](./src/OpenTelemetry.Instrumentation.AspNetCore/README.md) * [Grpc.Net.Client](./src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md) * [HTTP clients](./src/OpenTelemetry.Instrumentation.Http/README.md) -* [Redis client](./src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md) * [SQL client](./src/OpenTelemetry.Instrumentation.SqlClient/README.md) Here are the [exporter diff --git a/build/Common.nonprod.props b/build/Common.nonprod.props index 26e96bc4725..45fbfd9505a 100644 --- a/build/Common.nonprod.props +++ b/build/Common.nonprod.props @@ -47,7 +47,6 @@ [12.0.2,13.0) [4.14.5,5.0) [6.1.0,7.0) - [2.1.58,3.0) [6.2.3] [2.4.3,3.0) [2.4.1,3.0) diff --git a/build/Common.props b/build/Common.props index 94f485cb7b8..b512b98b529 100644 --- a/build/Common.props +++ b/build/Common.props @@ -39,8 +39,7 @@ [1.0.0,2.0) [1.0.0,2.0) [0.12.1,0.13) - 1.2.0 - [2.1.58,3.0) + 1.3.0 [1.2.0-beta.354,2.0) 1.4.0 6.0.0 diff --git a/build/docker-compose.net5.0.yml b/build/docker-compose.net5.0.yml deleted file mode 100644 index 53d82d8982d..00000000000 --- a/build/docker-compose.net5.0.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: '3.7' - -services: - tests: - build: - args: - PUBLISH_FRAMEWORK: net5.0 - SDK_VERSION: 5.0 diff --git a/docs/trace/extending-the-sdk/README.md b/docs/trace/extending-the-sdk/README.md index fd2263ce6f5..09058fc41fb 100644 --- a/docs/trace/extending-the-sdk/README.md +++ b/docs/trace/extending-the-sdk/README.md @@ -83,8 +83,8 @@ may be used as a reference. The [inspiration of the OpenTelemetry project](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/overview.md#instrumentation-libraries) -is to make every library observable out of the box by having -them call OpenTelemetry API directly. However, many libraries will not have such +is to make every library observable out of the box by having them call +OpenTelemetry API directly. However, many libraries will not have such integration, and as such there is a need for a separate library which would inject such calls, using mechanisms such as wrapping interfaces, subscribing to library-specific callbacks, or translating existing telemetry into OpenTelemetry @@ -103,11 +103,11 @@ the following instrumentation libraries. The individual docs for them describes the library they instrument, and steps for enabling them. * [ASP.NET](../../../src/OpenTelemetry.Instrumentation.AspNet/README.md) -* [ASP.NET Core](../../../src/OpenTelemetry.Instrumentation.AspNetCore/README.md) -* [gRPC client](../../../src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md) +* [ASP.NET + Core](../../../src/OpenTelemetry.Instrumentation.AspNetCore/README.md) +* [gRPC + client](../../../src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md) * [HTTP clients](../../../src/OpenTelemetry.Instrumentation.Http/README.md) -* [Redis - client](../../../src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md) * [SQL client](../../../src/OpenTelemetry.Instrumentation.SqlClient/README.md) More community contributed instrumentations are available in [OpenTelemetry .NET @@ -135,13 +135,9 @@ modify to emit activities directly.* Writing an instrumentation library typically involves 3 steps. 1. First step involves "hijacking" into the target library. The exact mechanism - of this depends on the target library itself. For example, StackExchangeRedis - library allows hooks into the library, and the [StackExchangeRedis - instrumentation - library](../../../src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md) - in this case, leverages them. Another example is System.Data.SqlClient for - .NET Framework, which publishes events using `EventSource`. The [SqlClient - instrumentation + of this depends on the target library itself. For example, + System.Data.SqlClient for .NET Framework, which publishes events using + `EventSource`. The [SqlClient instrumentation library](../../../src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs), in this case subscribes to the `EventSource` callbacks. @@ -151,20 +147,19 @@ Writing an instrumentation library typically involves 3 steps. target instrumented library. Irrespective of the actual mechanism used in first step, this should be uniform across all instrumentation libraries. The `ActivitySource` must be created using the name and version of the - instrumentation library (eg: - "OpenTelemetry.Instrumentation.StackExchangeRedis") and *not* the - instrumented library (eg: "StackExchange.Redis") - 1. [Context Propagation](../../../src/OpenTelemetry.Api/README.md#context-propagation): - If your library initiates out of process requests or - accepts them, the library needs to - [inject the `PropagationContext`](../../../examples/MicroserviceExample/Utils/Messaging/MessageSender.cs) - to outgoing requests and - [extract the context](../../../examples/MicroserviceExample/Utils/Messaging/MessageReceiver.cs) - and hydrate the Activity/Baggage upon receiving incoming requests. - This is only required if you're using your own protocol to - communicate over the wire. - (i.e. If you're using an already instrumented HttpClient or GrpcClient, - this is already provided to you and **do not require** + instrumentation library (eg: "OpenTelemetry.Instrumentation.Http") and *not* + the instrumented library (eg: "System.Net.Http") + 1. [Context + Propagation](../../../src/OpenTelemetry.Api/README.md#context-propagation): + If your library initiates out of process requests or accepts them, the + library needs to [inject the + `PropagationContext`](../../../examples/MicroserviceExample/Utils/Messaging/MessageSender.cs) + to outgoing requests and [extract the + context](../../../examples/MicroserviceExample/Utils/Messaging/MessageReceiver.cs) + and hydrate the Activity/Baggage upon receiving incoming requests. This is + only required if you're using your own protocol to communicate over the + wire. (i.e. If you're using an already instrumented HttpClient or + GrpcClient, this is already provided to you and **do not require** injecting/extracting `PropagationContext` explicitly again.) 3. Third step is an optional step, and involves providing extension methods on @@ -179,8 +174,8 @@ Writing an instrumentation library typically involves 3 steps. extension method on `TracerProviderBuilder`. Inside this extension method, it should call the `AddInstrumentation` method, and `AddSource` method to enable its ActivitySource for the provider. An example - instrumentation using this approach is [StackExchangeRedis - instrumentation](../../../src/OpenTelemetry.Instrumentation.StackExchangeRedis/TracerProviderBuilderExtensions.cs) + instrumentation using this approach is [SqlClient + instrumentation](../../../src/OpenTelemetry.Instrumentation.SqlClient/TracerProviderBuilderExtensions.cs) 2. If the instrumentation library does not requires any state management tied to that of `TracerProvider`, then providing `TracerProviderBuilder` @@ -326,16 +321,16 @@ A demo sampler is shown [here](./MySampler.cs). ## Resource Detector -OpenTelemetry .NET SDK provides a resource detector for detecting -resource information from the `OTEL_RESOURCE_ATTRIBUTES` and -`OTEL_SERVICE_NAME` environment variables. +OpenTelemetry .NET SDK provides a resource detector for detecting resource +information from the `OTEL_RESOURCE_ATTRIBUTES` and `OTEL_SERVICE_NAME` +environment variables. Custom resource detectors can be implemented: * ResourceDetectors should inherit from - `OpenTelemetry.Resources.IResourceDetector`, (which belongs - to the [OpenTelemetry](../../../src/OpenTelemetry/README.md) - package), and implement the `Detect` method. + `OpenTelemetry.Resources.IResourceDetector`, (which belongs to the + [OpenTelemetry](../../../src/OpenTelemetry/README.md) package), and implement + the `Detect` method. A demo ResourceDetector is shown [here](./MyResourceDetector.cs). diff --git a/examples/Console/Examples.Console.csproj b/examples/Console/Examples.Console.csproj index 9a8217606ca..26556b21e48 100644 --- a/examples/Console/Examples.Console.csproj +++ b/examples/Console/Examples.Console.csproj @@ -19,7 +19,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -27,7 +26,6 @@ - diff --git a/examples/Console/Program.cs b/examples/Console/Program.cs index ae80904ba5e..b7adda5f75c 100644 --- a/examples/Console/Program.cs +++ b/examples/Console/Program.cs @@ -46,7 +46,7 @@ public class Program /// Arguments from command line. public static void Main(string[] args) { - Parser.Default.ParseArguments(args) + Parser.Default.ParseArguments(args) .MapResult( (JaegerOptions options) => TestJaegerExporter.Run(options.Host, options.Port), (ZipkinOptions options) => TestZipkinExporter.Run(options.Uri), @@ -55,7 +55,6 @@ public static void Main(string[] args) (LogsOptions options) => TestLogs.Run(options), (GrpcNetClientOptions options) => TestGrpcNetClient.Run(), (HttpClientOptions options) => TestHttpClient.Run(), - (RedisOptions options) => TestRedis.Run(options.Uri), (ZPagesOptions options) => TestZPagesExporter.Run(), (ConsoleOptions options) => TestConsoleExporter.Run(options), (OpenTelemetryShimOptions options) => TestOTelShimWithConsoleExporter.Run(options), @@ -127,13 +126,6 @@ internal class HttpClientOptions { } - [Verb("redis", HelpText = "Specify the options required to test Redis with Zipkin")] - internal class RedisOptions - { - [Option('u', "uri", HelpText = "Please specify the uri of Zipkin backend", Required = true)] - public string Uri { get; set; } - } - [Verb("zpages", HelpText = "Specify the options required to test ZPages")] internal class ZPagesOptions { diff --git a/examples/Console/TestRedis.cs b/examples/Console/TestRedis.cs deleted file mode 100644 index 60b4025aa7b..00000000000 --- a/examples/Console/TestRedis.cs +++ /dev/null @@ -1,111 +0,0 @@ -// -// 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. -// -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; -using OpenTelemetry; -using OpenTelemetry.Trace; -using StackExchange.Redis; - -namespace Examples.Console -{ - internal class TestRedis - { - internal static object Run(string zipkinUri) - { - /* - * Setup redis service inside local docker. - * docker run --name opentelemetry-redis-test -d -p 6379:6379 redis - * - * If you face any issue with the first command, do the following ones: - * docker exec -it opentelemetry-redis-test sh - * redis-cli - * set bind 0.0.0.0 - * save - */ - - // connect to the redis server. The default port 6379 will be used. - var connection = ConnectionMultiplexer.Connect("localhost"); - - // Configure exporter to export traces to Zipkin - using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddZipkinExporter(o => - { - o.Endpoint = new Uri(zipkinUri); - }) - .AddRedisInstrumentation(connection, options => - { - // changing flushinterval from 10s to 5s - options.FlushInterval = TimeSpan.FromSeconds(5); - }) - .AddSource("redis-test") - .Build(); - - ActivitySource activitySource = new ActivitySource("redis-test"); - - // select a database (by default, DB = 0) - var db = connection.GetDatabase(); - - // Create a scoped activity. It will end automatically when using statement ends - using (activitySource.StartActivity("Main")) - { - System.Console.WriteLine("About to do a busy work"); - for (var i = 0; i < 10; i++) - { - DoWork(db, activitySource); - } - } - - System.Console.Write("Press ENTER to stop."); - System.Console.ReadLine(); - - return null; - } - - private static void DoWork(IDatabase db, ActivitySource activitySource) - { - // Start another activity. If another activity was already started, it'll use that activity as the parent activity. - // In this example, the main method already started a activity, so that'll be the parent activity, and this will be - // a child activity. - using Activity activity = activitySource.StartActivity("DoWork"); - try - { - db.StringSet("key", "value " + DateTime.Now.ToLongDateString()); - - System.Console.WriteLine("Doing busy work"); - Thread.Sleep(1000); - - // run a command, in this case a GET - var myVal = db.StringGet("key"); - - System.Console.WriteLine(myVal); - } - catch (ArgumentOutOfRangeException e) - { - activity.SetStatus(Status.Error.WithDescription(e.ToString())); - } - - // Annotate our activity to capture metadata about our operation - var attributes = new Dictionary - { - { "use", "demo" }, - }; - ActivityTagsCollection eventTags = new ActivityTagsCollection(attributes); - activity.AddEvent(new ActivityEvent("Invoking DoWork", default, eventTags)); - } - } -} diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index b8489e381ba..26664dcb8a9 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -2,6 +2,19 @@ ## Unreleased +## 1.3.0 + +Released 2022-Jun-03 + +## 1.3.0-rc.2 + +Released 2022-June-1 + +* `B3Propagator` class from `OpenTelemetry.Extensions.Propagators` namespace has + been deprecated and moved as is to a new `OpenTelemetry.Extensions.Propagators` + namespace, shipped as part of the `OpenTelemetry.Extensions.Propagators` package. + It will be removed in the next major release, see issue [#3259](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3259) + ## 1.3.0-beta.2 Released 2022-May-16 diff --git a/src/OpenTelemetry.Api/Context/Propagation/B3Propagator.cs b/src/OpenTelemetry.Api/Context/Propagation/B3Propagator.cs index 229c1b341ea..5d1b61089f7 100644 --- a/src/OpenTelemetry.Api/Context/Propagation/B3Propagator.cs +++ b/src/OpenTelemetry.Api/Context/Propagation/B3Propagator.cs @@ -25,7 +25,9 @@ namespace OpenTelemetry.Context.Propagation { /// /// A text map propagator for B3. See https://github.com/openzipkin/b3-propagation. + /// This class has been deprecated in favour of OpenTelemetry.Extensions.Propagators package. /// + [Obsolete("Use B3Propagator class from OpenTelemetry.Extensions.Propagators namespace, shipped as part of OpenTelemetry.Extensions.Propagators package.")] public sealed class B3Propagator : TextMapPropagator { internal const string XB3TraceId = "X-B3-TraceId"; @@ -58,6 +60,7 @@ public sealed class B3Propagator : TextMapPropagator /// /// Initializes a new instance of the class. /// + [Obsolete("Use B3Propagator class from OpenTelemetry.Extensions.Propagators namespace, shipped as part of OpenTelemetry.Extensions.Propagators package.")] public B3Propagator() : this(false) { @@ -67,6 +70,7 @@ public B3Propagator() /// Initializes a new instance of the class. /// /// Determines whether to use single or multiple headers when extracting or injecting span context. + [Obsolete("Use B3Propagator class from OpenTelemetry.Extensions.Propagators namespace, shipped as part of OpenTelemetry.Extensions.Propagators package.")] public B3Propagator(bool singleHeader) { this.singleHeader = singleHeader; @@ -76,7 +80,10 @@ public B3Propagator(bool singleHeader) public override ISet Fields => AllFields; /// + [Obsolete("Use B3Propagator class from OpenTelemetry.Extensions.Propagators namespace, shipped as part of OpenTelemetry.Extensions.Propagators package.")] +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member public override PropagationContext Extract(PropagationContext context, T carrier, Func> getter) +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member { if (context.ActivityContext.IsValid()) { @@ -107,7 +114,10 @@ public override PropagationContext Extract(PropagationContext context, T carr } /// + [Obsolete("Use B3Propagator class from OpenTelemetry.Extensions.Propagators namespace, shipped as part of OpenTelemetry.Extensions.Propagators package.")] +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member public override void Inject(PropagationContext context, T carrier, Action setter) +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member { if (context.ActivityContext.TraceId == default || context.ActivityContext.SpanId == default) { diff --git a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj index 82869c95ab9..40c2e7d7b46 100644 --- a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj +++ b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net462 @@ -9,12 +9,6 @@ core- - - - false - - diff --git a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md index abacb304cfb..227e032b5d1 100644 --- a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md @@ -2,6 +2,29 @@ ## Unreleased +## 1.3.0 + +Released 2022-Jun-03 + +## 1.3.0-rc.2 + +Released 2022-June-1 + +* Improve the conversion and formatting of attribute values. + The list of data types that must be supported per the + [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/common#attribute) + is more narrow than what the .NET OpenTelemetry SDK supports. Numeric + [built-in value types](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/built-in-types) + are supported by converting to a `long` or `double` as appropriate except for + numeric types that could cause overflow (`ulong`) or rounding (`decimal`) + which are converted to strings. Non-numeric built-in types - `string`, + `char`, `bool` are supported. All other types are converted to a `string`. + Array values are also supported. + ([#3311](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3311)) +* Fix conversion of array-valued attributes. They were previously + converted to a string like "System.String[]". + ([#3311](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3311)) + ## 1.3.0-beta.2 Released 2022-May-16 diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleActivityExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleActivityExporter.cs index 5d0ed336e81..9c08ce59f27 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleActivityExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleActivityExporter.cs @@ -14,7 +14,6 @@ // limitations under the License. // -using System; using System.Diagnostics; using System.Linq; using OpenTelemetry.Resources; @@ -71,13 +70,10 @@ public override ExportResult Export(in Batch batch) continue; } - if (tag.Value is not Array array) + if (ConsoleTagTransformer.Instance.TryTransformTag(tag, out var result)) { - this.WriteLine($" {tag.Key}: {tag.Value}"); - continue; + this.WriteLine($" {result}"); } - - this.WriteLine($" {tag.Key}: [{string.Join(", ", array.Cast())}]"); } } @@ -106,7 +102,10 @@ public override ExportResult Export(in Batch batch) this.WriteLine($" {activityEvent.Name} [{activityEvent.Timestamp}]"); foreach (var attribute in activityEvent.Tags) { - this.WriteLine($" {attribute.Key}: {attribute.Value}"); + if (ConsoleTagTransformer.Instance.TryTransformTag(attribute, out var result)) + { + this.WriteLine($" {result}"); + } } } } @@ -117,6 +116,13 @@ public override ExportResult Export(in Batch batch) foreach (var activityLink in activity.Links) { this.WriteLine($" {activityLink.Context.TraceId} {activityLink.Context.SpanId}"); + foreach (var attribute in activityLink.Tags) + { + if (ConsoleTagTransformer.Instance.TryTransformTag(attribute, out var result)) + { + this.WriteLine($" {result}"); + } + } } } @@ -126,7 +132,10 @@ public override ExportResult Export(in Batch batch) this.WriteLine("Resource associated with Activity:"); foreach (var resourceAttribute in resource.Attributes) { - this.WriteLine($" {resourceAttribute.Key}: {resourceAttribute.Value}"); + if (ConsoleTagTransformer.Instance.TryTransformTag(resourceAttribute, out var result)) + { + this.WriteLine($" {result}"); + } } } diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs index b8e2cde014d..2e3731e1d3b 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs @@ -62,13 +62,13 @@ public override ExportResult Export(in Batch batch) // Special casing {OriginalFormat} // See https://github.com/open-telemetry/opentelemetry-dotnet/pull/3182 // for explanation. - if (logRecord.StateValues[i].Key.Equals("{OriginalFormat}")) - { - this.WriteLine($"{string.Empty,-4}{"OriginalFormat (a.k.a. Body)",-RightPaddingLength}{logRecord.StateValues[i].Value}"); - } - else + var valueToTransform = logRecord.StateValues[i].Key.Equals("{OriginalValue}") + ? new KeyValuePair("OriginalFormat (a.k.a Body)", logRecord.StateValues[i].Value) + : logRecord.StateValues[i]; + + if (ConsoleTagTransformer.Instance.TryTransformTag(valueToTransform, out var result)) { - this.WriteLine($"{string.Empty,-4}{logRecord.StateValues[i].Key,-RightPaddingLength}{logRecord.StateValues[i].Value}"); + this.WriteLine($"{string.Empty,-4}{result}"); } } } @@ -100,7 +100,10 @@ void ProcessScope(LogRecordScope scope, ConsoleLogRecordExporter exporter) foreach (KeyValuePair scopeItem in scope) { - exporter.WriteLine($"[Scope.{scopeDepth}]:{scopeItem.Key,-RightPaddingLength}{scopeItem.Value}"); + if (ConsoleTagTransformer.Instance.TryTransformTag(scopeItem, out var result)) + { + exporter.WriteLine($"[Scope.{scopeDepth}]:{result}"); + } } } @@ -110,7 +113,10 @@ void ProcessScope(LogRecordScope scope, ConsoleLogRecordExporter exporter) this.WriteLine("\nResource associated with LogRecord:"); foreach (var resourceAttribute in resource.Attributes) { - this.WriteLine($"{resourceAttribute.Key}: {resourceAttribute.Value}"); + if (ConsoleTagTransformer.Instance.TryTransformTag(resourceAttribute, out var result)) + { + this.WriteLine(result); + } } } diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs index ca4cc0e1199..f5833362d79 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs @@ -37,11 +37,12 @@ public override ExportResult Export(in Batch batch) this.resource = this.ParentProvider.GetResource(); if (this.resource != Resource.Empty) { + this.WriteLine("Resource associated with Metric:"); foreach (var resourceAttribute in this.resource.Attributes) { - if (resourceAttribute.Key.Equals("service.name")) + if (ConsoleTagTransformer.Instance.TryTransformTag(resourceAttribute, out var result)) { - this.WriteLine("Service.Name=" + resourceAttribute.Value); + this.WriteLine($" {result}"); } } } @@ -80,10 +81,11 @@ public override ExportResult Export(in Batch batch) StringBuilder tagsBuilder = new StringBuilder(); foreach (var tag in metricPoint.Tags) { - tagsBuilder.Append(tag.Key); - tagsBuilder.Append(':'); - tagsBuilder.Append(tag.Value); - tagsBuilder.Append(' '); + if (ConsoleTagTransformer.Instance.TryTransformTag(tag, out var result)) + { + tagsBuilder.Append(result); + tagsBuilder.Append(' '); + } } var tags = tagsBuilder.ToString().TrimEnd(); diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleTagTransformer.cs b/src/OpenTelemetry.Exporter.Console/ConsoleTagTransformer.cs new file mode 100644 index 00000000000..e87862e5b55 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Console/ConsoleTagTransformer.cs @@ -0,0 +1,40 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter; + +internal sealed class ConsoleTagTransformer : TagTransformer +{ + private ConsoleTagTransformer() + { + } + + public static ConsoleTagTransformer Instance { get; } = new(); + + protected override string TransformIntegralTag(string key, long value) => $"{key}: {value}"; + + protected override string TransformFloatingPointTag(string key, double value) => $"{key}: {value}"; + + protected override string TransformBooleanTag(string key, bool value) => $"{key}: {(value ? "true" : "false")}"; + + protected override string TransformStringTag(string key, string value) => $"{key}: {value}"; + + protected override string TransformArrayTag(string key, Array array) + => this.TransformStringTag(key, System.Text.Json.JsonSerializer.Serialize(array)); +} diff --git a/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj b/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj index f97c1178f4f..028440a5896 100644 --- a/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj +++ b/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj @@ -12,19 +12,20 @@ $(NoWarn),1591 - - - false - + + + + + + diff --git a/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Shipped.txt index 945bf45920f..e2db05e1b80 100644 --- a/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Shipped.txt @@ -1,7 +1,21 @@ OpenTelemetry.Exporter.InMemoryExporter OpenTelemetry.Exporter.InMemoryExporter.InMemoryExporter(System.Collections.Generic.ICollection exportedItems) -> void OpenTelemetry.Logs.InMemoryExporterLoggingExtensions +OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions +OpenTelemetry.Metrics.MetricSnapshot +OpenTelemetry.Metrics.MetricSnapshot.Description.get -> string +OpenTelemetry.Metrics.MetricSnapshot.MeterName.get -> string +OpenTelemetry.Metrics.MetricSnapshot.MeterVersion.get -> string +OpenTelemetry.Metrics.MetricSnapshot.MetricPoints.get -> System.Collections.Generic.IReadOnlyList +OpenTelemetry.Metrics.MetricSnapshot.MetricSnapshot(OpenTelemetry.Metrics.Metric metric) -> void +OpenTelemetry.Metrics.MetricSnapshot.MetricType.get -> OpenTelemetry.Metrics.MetricType +OpenTelemetry.Metrics.MetricSnapshot.Name.get -> string +OpenTelemetry.Metrics.MetricSnapshot.Unit.get -> string OpenTelemetry.Trace.InMemoryExporterHelperExtensions override OpenTelemetry.Exporter.InMemoryExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult static OpenTelemetry.Logs.InMemoryExporterLoggingExtensions.AddInMemoryExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Trace.InMemoryExporterHelperExtensions.AddInMemoryExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt index ca21920895c..e69de29bb2d 100644 --- a/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,3 +0,0 @@ -OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions -static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder -static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Shipped.txt index 945bf45920f..e2db05e1b80 100644 --- a/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Shipped.txt @@ -1,7 +1,21 @@ OpenTelemetry.Exporter.InMemoryExporter OpenTelemetry.Exporter.InMemoryExporter.InMemoryExporter(System.Collections.Generic.ICollection exportedItems) -> void OpenTelemetry.Logs.InMemoryExporterLoggingExtensions +OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions +OpenTelemetry.Metrics.MetricSnapshot +OpenTelemetry.Metrics.MetricSnapshot.Description.get -> string +OpenTelemetry.Metrics.MetricSnapshot.MeterName.get -> string +OpenTelemetry.Metrics.MetricSnapshot.MeterVersion.get -> string +OpenTelemetry.Metrics.MetricSnapshot.MetricPoints.get -> System.Collections.Generic.IReadOnlyList +OpenTelemetry.Metrics.MetricSnapshot.MetricSnapshot(OpenTelemetry.Metrics.Metric metric) -> void +OpenTelemetry.Metrics.MetricSnapshot.MetricType.get -> OpenTelemetry.Metrics.MetricType +OpenTelemetry.Metrics.MetricSnapshot.Name.get -> string +OpenTelemetry.Metrics.MetricSnapshot.Unit.get -> string OpenTelemetry.Trace.InMemoryExporterHelperExtensions override OpenTelemetry.Exporter.InMemoryExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult static OpenTelemetry.Logs.InMemoryExporterLoggingExtensions.AddInMemoryExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Trace.InMemoryExporterHelperExtensions.AddInMemoryExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index ca21920895c..e69de29bb2d 100644 --- a/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.InMemory/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,3 +0,0 @@ -OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions -static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder -static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md index 4b7ad94f5c3..17fa5bd8c7d 100644 --- a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +## 1.3.0 + +Released 2022-Jun-03 + +## 1.3.0-rc.2 + +Released 2022-June-1 + +* Adds new `AddInMemoryExporter` extension method to export `Metric` as new + type `MetricSnapshot`. + ([#2361](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2361)) + ## 1.3.0-beta.2 Released 2022-May-16 diff --git a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs index d76995f8fb6..8dab7b51d96 100644 --- a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs +++ b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System; using System.Collections.Generic; namespace OpenTelemetry.Exporter @@ -22,13 +23,22 @@ public class InMemoryExporter : BaseExporter where T : class { private readonly ICollection exportedItems; + private readonly Func, ExportResult> onExport; public InMemoryExporter(ICollection exportedItems) { this.exportedItems = exportedItems; + this.onExport = (Batch batch) => this.DefaultExport(batch); } - public override ExportResult Export(in Batch batch) + internal InMemoryExporter(Func, ExportResult> exportFunc) + { + this.onExport = exportFunc; + } + + public override ExportResult Export(in Batch batch) => this.onExport(batch); + + private ExportResult DefaultExport(in Batch batch) { if (this.exportedItems == null) { diff --git a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs index 9809b09552b..f817f5744fa 100644 --- a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs +++ b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs @@ -33,10 +33,28 @@ public static class InMemoryExporterMetricsExtensions /// /// Adds InMemory metric exporter to the using default options. /// + /// + /// Be aware that may continue to be updated after export. + /// /// builder to use. - /// Collection which will be populated with the exported MetricItem. + /// Collection which will be populated with the exported . /// The instance of to chain the calls. public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder builder, ICollection exportedItems) + { + return builder.AddInMemoryExporter(exportedItems: exportedItems, configureMetricReader: null); + } + + /// + /// Adds InMemory metric exporter to the . + /// + /// + /// Be aware that may continue to be updated after export. + /// + /// builder to use. + /// Collection which will be populated with the exported . + /// configuration options. + /// The instance of to chain the calls. + public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder builder, ICollection exportedItems, Action configureMetricReader) { Guard.ThrowIfNull(builder); Guard.ThrowIfNull(exportedItems); @@ -45,21 +63,45 @@ public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder { return deferredMeterProviderBuilder.Configure((sp, builder) => { - AddInMemoryExporter(builder, exportedItems, sp.GetOptions(), null); + AddInMemoryExporter(builder, exportedItems, sp.GetOptions(), configureMetricReader); }); } - return AddInMemoryExporter(builder, exportedItems, new MetricReaderOptions(), null); + return AddInMemoryExporter(builder, exportedItems, new MetricReaderOptions(), configureMetricReader); } /// /// Adds InMemory metric exporter to the using default options. + /// The exporter will be setup to export . /// + /// + /// Use this if you need a copy of that will not be updated after export. + /// /// builder to use. - /// Collection which will be populated with the exported MetricItem. + /// Collection which will be populated with the exported represented as . + /// The instance of to chain the calls. + public static MeterProviderBuilder AddInMemoryExporter( + this MeterProviderBuilder builder, + ICollection exportedItems) + { + return builder.AddInMemoryExporter(exportedItems: exportedItems, configureMetricReader: null); + } + + /// + /// Adds InMemory metric exporter to the . + /// The exporter will be setup to export . + /// + /// + /// Use this if you need a copy of that will not be updated after export. + /// + /// builder to use. + /// Collection which will be populated with the exported represented as . /// configuration options. /// The instance of to chain the calls. - public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder builder, ICollection exportedItems, Action configureMetricReader) + public static MeterProviderBuilder AddInMemoryExporter( + this MeterProviderBuilder builder, + ICollection exportedItems, + Action configureMetricReader) { Guard.ThrowIfNull(builder); Guard.ThrowIfNull(exportedItems); @@ -93,5 +135,40 @@ private static MeterProviderBuilder AddInMemoryExporter( return builder.AddReader(metricReader); } + + private static MeterProviderBuilder AddInMemoryExporter( + MeterProviderBuilder builder, + ICollection exportedItems, + MetricReaderOptions metricReaderOptions, + Action configureMetricReader) + { + configureMetricReader?.Invoke(metricReaderOptions); + + var metricExporter = new InMemoryExporter( + exportFunc: metricBatch => ExportMetricSnapshot(metricBatch, exportedItems)); + + var metricReader = PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader( + metricExporter, + metricReaderOptions, + DefaultExportIntervalMilliseconds, + DefaultExportTimeoutMilliseconds); + + return builder.AddReader(metricReader); + } + + private static ExportResult ExportMetricSnapshot(in Batch batch, ICollection exportedItems) + { + if (exportedItems == null) + { + return ExportResult.Failure; + } + + foreach (var metric in batch) + { + exportedItems.Add(new MetricSnapshot(metric)); + } + + return ExportResult.Success; + } } } diff --git a/src/OpenTelemetry.Exporter.InMemory/MetricSnapshot.cs b/src/OpenTelemetry.Exporter.InMemory/MetricSnapshot.cs new file mode 100644 index 00000000000..635e3549310 --- /dev/null +++ b/src/OpenTelemetry.Exporter.InMemory/MetricSnapshot.cs @@ -0,0 +1,58 @@ +// +// 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. +// + +using System.Collections.Generic; + +namespace OpenTelemetry.Metrics +{ + /// + /// This class represents a selective copy of . + /// This contains the minimum fields and properties needed for most + /// unit testing scenarios. + /// + public class MetricSnapshot + { + private readonly MetricStreamIdentity instrumentIdentity; + + public MetricSnapshot(Metric metric) + { + this.instrumentIdentity = metric.InstrumentIdentity; + this.MetricType = metric.MetricType; + + List metricPoints = new(); + foreach (ref readonly var metricPoint in metric.GetMetricPoints()) + { + metricPoints.Add(metricPoint.Copy()); + } + + this.MetricPoints = metricPoints; + } + + public string Name => this.instrumentIdentity.InstrumentName; + + public string Description => this.instrumentIdentity.Description; + + public string Unit => this.instrumentIdentity.Unit; + + public string MeterName => this.instrumentIdentity.MeterName; + + public MetricType MetricType { get; } + + public string MeterVersion => this.instrumentIdentity.MeterVersion; + + public IReadOnlyList MetricPoints { get; } + } +} diff --git a/src/OpenTelemetry.Exporter.InMemory/OpenTelemetry.Exporter.InMemory.csproj b/src/OpenTelemetry.Exporter.InMemory/OpenTelemetry.Exporter.InMemory.csproj index bdb3c634cd8..6a014d3f5dd 100644 --- a/src/OpenTelemetry.Exporter.InMemory/OpenTelemetry.Exporter.InMemory.csproj +++ b/src/OpenTelemetry.Exporter.InMemory/OpenTelemetry.Exporter.InMemory.csproj @@ -12,23 +12,11 @@ $(NoWarn),1591 - - - false - - - - diff --git a/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md b/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md index 4b0cab56f41..78402461db4 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md @@ -2,6 +2,33 @@ ## Unreleased +## 1.3.0 + +Released 2022-Jun-03 + +## 1.3.0-rc.2 + +Released 2022-June-1 + +* Improve the conversion and formatting of attribute values. + The list of data types that must be supported per the + [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/common#attribute) + is more narrow than what the .NET OpenTelemetry SDK supports. Numeric + [built-in value types](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/built-in-types) + are supported by converting to a `long` or `double` as appropriate except for + numeric types that could cause overflow (`ulong`) or rounding (`decimal`) + which are converted to strings. Non-numeric built-in types - `string`, + `char`, `bool` are supported. All other types are converted to a `string`. + Array values are also supported. + ([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281)) +* Fix conversion of array-valued resource attributes. They were previously + converted to a string like "System.String[]". + ([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281)) +* Fix exporting of array-valued attributes on an `Activity`. Previously, each + item in the array would result in a new tag on an exported `Activity`. Now, + array-valued attributes are serialzed to a JSON-array representation. + ([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281)) + ## 1.3.0-beta.2 Released 2022-May-16 diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerActivityExtensions.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerActivityExtensions.cs index 33a3f8ee332..99be25fdbc9 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerActivityExtensions.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerActivityExtensions.cs @@ -230,20 +230,6 @@ public static JaegerSpanRef ToJaegerSpanRef(this in ActivityLink link) return new JaegerSpanRef(refType, traceId.Low, traceId.High, spanId.Low); } - public static JaegerTag ToJaegerTag(this KeyValuePair attribute) - { - return attribute.Value switch - { - string s => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: s), - int i => new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: Convert.ToInt64(i)), - long l => new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: l), - float f => new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: Convert.ToDouble(f)), - double d => new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: d), - bool b => new JaegerTag(attribute.Key, JaegerTagType.BOOL, vBool: b), - _ => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: attribute.Value.ToString()), - }; - } - public static long ToEpochMicroseconds(this DateTime utcDateTime) { // Truncate sub-microsecond precision before offsetting by the Unix Epoch to avoid @@ -260,42 +246,6 @@ public static long ToEpochMicroseconds(this DateTimeOffset timestamp) return microseconds - UnixEpochMicroseconds; } - private static void ProcessJaegerTagArray(ref PooledList tags, KeyValuePair activityTag) - { - if (activityTag.Value is int[] intArray) - { - foreach (var item in intArray) - { - JaegerTag jaegerTag = new JaegerTag(activityTag.Key, JaegerTagType.LONG, vLong: Convert.ToInt64(item)); - PooledList.Add(ref tags, jaegerTag); - } - } - else if (activityTag.Value is string[] stringArray) - { - foreach (var item in stringArray) - { - JaegerTag jaegerTag = new JaegerTag(activityTag.Key, JaegerTagType.STRING, vStr: item); - PooledList.Add(ref tags, jaegerTag); - } - } - else if (activityTag.Value is bool[] boolArray) - { - foreach (var item in boolArray) - { - JaegerTag jaegerTag = new JaegerTag(activityTag.Key, JaegerTagType.BOOL, vBool: item); - PooledList.Add(ref tags, jaegerTag); - } - } - else if (activityTag.Value is double[] doubleArray) - { - foreach (var item in doubleArray) - { - JaegerTag jaegerTag = new JaegerTag(activityTag.Key, JaegerTagType.DOUBLE, vDouble: item); - PooledList.Add(ref tags, jaegerTag); - } - } - } - private struct TagEnumerationState : IActivityEnumerator>, PeerServiceResolver.IPeerServiceState { public PooledList Tags; @@ -316,14 +266,15 @@ private struct TagEnumerationState : IActivityEnumerator activityTag) { - if (activityTag.Value is Array) - { - ProcessJaegerTagArray(ref this.Tags, activityTag); - } - else if (activityTag.Value != null) + if (activityTag.Value != null) { var key = activityTag.Key; - var jaegerTag = activityTag.ToJaegerTag(); + + if (!JaegerTagTransformer.Instance.TryTransformTag(activityTag, out var jaegerTag)) + { + return true; + } + if (jaegerTag.VStr != null) { PeerServiceResolver.InspectTag(ref this, key, jaegerTag.VStr); @@ -400,18 +351,14 @@ private struct EventTagsEnumerationState : IActivityEnumerator tag) { - if (tag.Value is Array) - { - ProcessJaegerTagArray(ref this.Tags, tag); - } - else if (tag.Value != null) + if (JaegerTagTransformer.Instance.TryTransformTag(tag, out var result)) { - PooledList.Add(ref this.Tags, tag.ToJaegerTag()); - } + PooledList.Add(ref this.Tags, result); - if (tag.Key == "event") - { - this.HasEvent = true; + if (tag.Key == "event") + { + this.HasEvent = true; + } } return true; diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagTransformer.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagTransformer.cs new file mode 100644 index 00000000000..ccc38b2efe7 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagTransformer.cs @@ -0,0 +1,52 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter.Jaeger.Implementation; + +internal sealed class JaegerTagTransformer : TagTransformer +{ + private JaegerTagTransformer() + { + } + + public static JaegerTagTransformer Instance { get; } = new(); + + protected override JaegerTag TransformIntegralTag(string key, long value) + { + return new JaegerTag(key, JaegerTagType.LONG, vLong: value); + } + + protected override JaegerTag TransformFloatingPointTag(string key, double value) + { + return new JaegerTag(key, JaegerTagType.DOUBLE, vDouble: value); + } + + protected override JaegerTag TransformBooleanTag(string key, bool value) + { + return new JaegerTag(key, JaegerTagType.BOOL, vBool: value); + } + + protected override JaegerTag TransformStringTag(string key, string value) + { + return new JaegerTag(key, JaegerTagType.STRING, vStr: value); + } + + protected override JaegerTag TransformArrayTag(string key, Array array) + => this.TransformStringTag(key, System.Text.Json.JsonSerializer.Serialize(array)); +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs index 95bb58587b1..1d76584748e 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs @@ -15,7 +15,6 @@ // using System.Collections.Generic; -using System.Linq; using System.Text; using Thrift.Protocol; using Thrift.Protocol.Entities; @@ -29,20 +28,6 @@ public Process(string serviceName) this.ServiceName = serviceName; } - public Process(string serviceName, IEnumerable> processTags) - : this(serviceName, processTags?.Select(pt => pt.ToJaegerTag()).ToDictionary(pt => pt.Key, pt => pt)) - { - } - - internal Process(string serviceName, Dictionary processTags) - : this(serviceName) - { - if (processTags != null) - { - this.Tags = processTags; - } - } - public string ServiceName { get; internal set; } internal Dictionary Tags { get; set; } diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs index 5d57747a57b..4a26ce813d4 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs @@ -145,12 +145,15 @@ internal void SetResourceAndInitializeBatch(Resource resource) } } - if (process.Tags == null) + if (JaegerTagTransformer.Instance.TryTransformTag(label, out var result)) { - process.Tags = new Dictionary(); - } + if (process.Tags == null) + { + process.Tags = new Dictionary(); + } - process.Tags[key] = label.ToJaegerTag(); + process.Tags[key] = result; + } } if (serviceName != null) diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs index 9845c0e0b77..b992048d338 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs @@ -47,11 +47,9 @@ public JaegerExporterOptions() { if (EnvironmentVariableHelper.LoadString(OTelProtocolEnvVarKey, out string protocolEnvVar)) { - var protocol = protocolEnvVar.ToJaegerExportProtocol(); - - if (protocol.HasValue) + if (JaegerExporterProtocolParser.TryParse(protocolEnvVar, out var protocol)) { - this.Protocol = protocol.Value; + this.Protocol = protocol; } else { diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterProtocolParser.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterProtocolParser.cs new file mode 100644 index 00000000000..52fb109350f --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterProtocolParser.cs @@ -0,0 +1,36 @@ +// +// 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. +// + +namespace OpenTelemetry.Exporter; + +internal static class JaegerExporterProtocolParser +{ + public static bool TryParse(string value, out JaegerExportProtocol result) + { + switch (value?.Trim()) + { + case "udp/thrift.compact": + result = JaegerExportProtocol.UdpCompactThrift; + return true; + case "http/thrift.binary": + result = JaegerExportProtocol.HttpBinaryThrift; + return true; + default: + result = default; + return false; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj index 5b8c06244cc..be74287c873 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj +++ b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj @@ -8,12 +8,6 @@ core- - - - false - - $(NoWarn),1591 @@ -33,10 +27,12 @@ + + diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md index 1b751b6d856..8a0a3f260ff 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.3.0-rc.2 + +Released 2022-June-1 + ## 1.0.0-rc9.3 Released 2022-Apr-15 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj index b6044b6bdc8..730c96a7519 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj @@ -4,6 +4,7 @@ netstandard2.1;netstandard2.0;net462 OpenTelemetry protocol exporter for OpenTelemetry .NET $(PackageTags);OTLP + core- - - false - - @@ -49,6 +43,8 @@ + + diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExportProtocolParser.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExportProtocolParser.cs new file mode 100644 index 00000000000..23062ce458b --- /dev/null +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExportProtocolParser.cs @@ -0,0 +1,37 @@ +// +// 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. +// + +namespace OpenTelemetry.Exporter +{ + internal static class OtlpExportProtocolParser + { + public static bool TryParse(string value, out OtlpExportProtocol result) + { + switch (value?.Trim()) + { + case "grpc": + result = OtlpExportProtocol.Grpc; + return true; + case "http/protobuf": + result = OtlpExportProtocol.HttpProtobuf; + return true; + default: + result = default; + return false; + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs index 020f57ee577..936da811fa4 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs @@ -69,10 +69,9 @@ public OtlpExporterOptions() if (EnvironmentVariableHelper.LoadString(ProtocolEnvVarName, out string protocolEnvVar)) { - var protocol = protocolEnvVar.ToOtlpExportProtocol(); - if (protocol.HasValue) + if (OtlpExportProtocolParser.TryParse(protocolEnvVar, out var protocol)) { - this.Protocol = protocol.Value; + this.Protocol = protocol; } else { diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptionsExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptionsExtensions.cs index 9d99caf1714..43a6c3a997b 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptionsExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptionsExtensions.cs @@ -121,14 +121,6 @@ public static THeaders GetHeaders(this OtlpExporterOptions options, Ac _ => throw new NotSupportedException($"Protocol {options.Protocol} is not supported."), }; - public static OtlpExportProtocol? ToOtlpExportProtocol(this string protocol) => - protocol.Trim() switch - { - "grpc" => OtlpExportProtocol.Grpc, - "http/protobuf" => OtlpExportProtocol.HttpProtobuf, - _ => null, - }; - public static void TryEnableIHttpClientFactoryIntegration(this OtlpExporterOptions options, IServiceProvider serviceProvider, string httpClientName) { if (serviceProvider != null diff --git a/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md index 12db71d8dd8..68055853b76 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.3.0-rc.2 + +Released 2022-June-1 + ## 1.3.0-beta.2 Released 2022-May-16 diff --git a/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md b/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md index b0c8dc1b431..cd272cb8e85 100644 --- a/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + * Removes .NET Framework 4.6.1. The minimum .NET Framework version supported is .NET 4.6.2. ([#3190](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3190)) diff --git a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md index 5585eaf7770..d62d7bc4efd 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md @@ -2,6 +2,33 @@ ## Unreleased +## 1.3.0 + +Released 2022-Jun-03 + +## 1.3.0-rc.2 + +Released 2022-June-1 + +* Improve the conversion and formatting of attribute values. + The list of data types that must be supported per the + [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/common#attribute) + is more narrow than what the .NET OpenTelemetry SDK supports. Numeric + [built-in value types](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/built-in-types) + are supported by converting to a `long` or `double` as appropriate except for + numeric types that could cause overflow (`ulong`) or rounding (`decimal`) + which are converted to strings. Non-numeric built-in types - `string`, + `char`, `bool` are supported. All other types are converted to a `string`. + Array values are also supported. + ([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281)) +* Fix conversion of array-valued resource attributes. They were previously + converted to a string like "System.String[]". + ([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281)) +* Fix exporting of array-valued attributes on an `Activity`. Previously, each + item in the array would result in a new tag on an exported `Activity`. Now, + array-valued attributes are serialzed to a JSON-array representation. + ([#3281](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3281)) + ## 1.3.0-beta.2 Released 2022-May-16 diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs index 1ee3b7cf236..ac75989f35a 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs @@ -17,7 +17,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Runtime.CompilerServices; using System.Text.Json; using System.Threading; using OpenTelemetry.Internal; @@ -178,12 +177,18 @@ public void Write(Utf8JsonWriter writer) { foreach (var tag in this.LocalEndpoint.Tags ?? Enumerable.Empty>()) { - writer.WriteString(tag.Key, ConvertObjectToString(tag.Value)); + if (ZipkinTagTransformer.Instance.TryTransformTag(tag, out var result)) + { + writer.WriteString(tag.Key, result); + } } foreach (var tag in this.Tags) { - writer.WriteString(tag.Key, ConvertObjectToString(tag.Value)); + if (ZipkinTagTransformer.Instance.TryTransformTag(tag, out var result)) + { + writer.WriteString(tag.Key, result); + } } } finally @@ -196,26 +201,5 @@ public void Write(Utf8JsonWriter writer) writer.WriteEndObject(); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string ConvertObjectToString(object obj) - { - return obj switch - { - string stringVal => stringVal, - bool boolVal => GetBoolString(boolVal), - int[] arrayValue => string.Join(",", arrayValue), - long[] arrayValue => string.Join(",", arrayValue), - double[] arrayValue => string.Join(",", arrayValue), - bool[] arrayValue => string.Join(",", arrayValue.Select(GetBoolString)), - _ => obj.ToString(), - }; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string GetBoolString(bool value) - { - return value ? "true" : "false"; - } } } diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagTransformer.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagTransformer.cs new file mode 100644 index 00000000000..0a7a0d85b2e --- /dev/null +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagTransformer.cs @@ -0,0 +1,40 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter.Zipkin.Implementation; + +internal sealed class ZipkinTagTransformer : TagTransformer +{ + private ZipkinTagTransformer() + { + } + + public static ZipkinTagTransformer Instance { get; } = new(); + + protected override string TransformIntegralTag(string key, long value) => value.ToString(); + + protected override string TransformFloatingPointTag(string key, double value) => value.ToString(); + + protected override string TransformBooleanTag(string key, bool value) => value ? "true" : "false"; + + protected override string TransformStringTag(string key, string value) => value; + + protected override string TransformArrayTag(string key, Array array) + => this.TransformStringTag(key, System.Text.Json.JsonSerializer.Serialize(array)); +} diff --git a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj index bd7d123d74f..381ab1ff009 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj +++ b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj @@ -7,12 +7,6 @@ core- - - - false - - @@ -28,6 +22,7 @@ + diff --git a/src/OpenTelemetry.Extensions.Hosting/CHANGELOG.md b/src/OpenTelemetry.Extensions.Hosting/CHANGELOG.md index bb8226784e9..799952828e8 100644 --- a/src/OpenTelemetry.Extensions.Hosting/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Hosting/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + ## 1.0.0-rc9.3 Released 2022-Apr-15 diff --git a/src/OpenTelemetry.Extensions.Propagators/B3Propagator.cs b/src/OpenTelemetry.Extensions.Propagators/B3Propagator.cs index 33f7022e059..8e84315fc24 100644 --- a/src/OpenTelemetry.Extensions.Propagators/B3Propagator.cs +++ b/src/OpenTelemetry.Extensions.Propagators/B3Propagator.cs @@ -88,13 +88,13 @@ public override PropagationContext Extract(PropagationContext context, T carr if (carrier == null) { - OpenTelemetryApiEventSource.Log.FailedToExtractActivityContext(nameof(B3Propagator), "null carrier"); + OpenTelemetryPropagatorsEventSource.Log.FailedToExtractActivityContext(nameof(B3Propagator), "null carrier"); return context; } if (getter == null) { - OpenTelemetryApiEventSource.Log.FailedToExtractActivityContext(nameof(B3Propagator), "null getter"); + OpenTelemetryPropagatorsEventSource.Log.FailedToExtractActivityContext(nameof(B3Propagator), "null getter"); return context; } @@ -113,19 +113,19 @@ public override void Inject(PropagationContext context, T carrier, Action(PropagationConte } catch (Exception e) { - OpenTelemetryApiEventSource.Log.ActivityContextExtractException(nameof(B3Propagator), e); + OpenTelemetryPropagatorsEventSource.Log.ActivityContextExtractException(nameof(B3Propagator), e); return context; } } @@ -259,7 +259,7 @@ private static PropagationContext ExtractFromSingleHeader(PropagationContext } catch (Exception e) { - OpenTelemetryApiEventSource.Log.ActivityContextExtractException(nameof(B3Propagator), e); + OpenTelemetryPropagatorsEventSource.Log.ActivityContextExtractException(nameof(B3Propagator), e); return context; } } diff --git a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md index d89c0d3c8dd..a9a12f2cb92 100644 --- a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +## 1.3.0 + +Released 2022-Jun-03 + +Use own EventSource named "OpenTelemetry.Extensions.Propagators" +for internal logging. + +## 1.3.0-rc.2 + +Released 2022-June-1 + * Initial release. This has been ported as is from [OpenTelemetry.Api](../OpenTelemetry.Api/README.md) package. diff --git a/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs b/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs index b175a36ce57..a3fa2e98da5 100644 --- a/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs +++ b/src/OpenTelemetry.Extensions.Propagators/JaegerPropagator.cs @@ -52,13 +52,13 @@ public override PropagationContext Extract(PropagationContext context, T carr if (carrier == null) { - OpenTelemetryApiEventSource.Log.FailedToExtractActivityContext(nameof(JaegerPropagator), "null carrier"); + OpenTelemetryPropagatorsEventSource.Log.FailedToExtractActivityContext(nameof(JaegerPropagator), "null carrier"); return context; } if (getter == null) { - OpenTelemetryApiEventSource.Log.FailedToExtractActivityContext(nameof(JaegerPropagator), "null getter"); + OpenTelemetryPropagatorsEventSource.Log.FailedToExtractActivityContext(nameof(JaegerPropagator), "null getter"); return context; } @@ -85,7 +85,7 @@ public override PropagationContext Extract(PropagationContext context, T carr } catch (Exception ex) { - OpenTelemetryApiEventSource.Log.ActivityContextExtractException(nameof(JaegerPropagator), ex); + OpenTelemetryPropagatorsEventSource.Log.ActivityContextExtractException(nameof(JaegerPropagator), ex); } return context; @@ -101,19 +101,19 @@ public override void Inject(PropagationContext context, T carrier, Actionnet462;netstandard2.0 OpenTelemetry Extensions Propagators $(PackageTags);distributed-tracing;AspNet;AspNetCore;B3 + core- true - - - - - - - false - - diff --git a/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs b/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs new file mode 100644 index 00000000000..fc22c92e87f --- /dev/null +++ b/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs @@ -0,0 +1,52 @@ +// +// 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. +// + +using System; +using System.Diagnostics.Tracing; + +namespace OpenTelemetry.Internal +{ + /// + /// EventSource implementation for OpenTelemetry Propagators. + /// This is used for internal logging of this library. + /// + [EventSource(Name = "OpenTelemetry.Extensions.Propagators")] + internal class OpenTelemetryPropagatorsEventSource : EventSource + { + public static OpenTelemetryPropagatorsEventSource Log = new(); + + [NonEvent] + public void ActivityContextExtractException(string format, Exception ex) + { + if (this.IsEnabled(EventLevel.Warning, EventKeywords.All)) + { + this.FailedToExtractActivityContext(format, ex.ToInvariantString()); + } + } + + [Event(1, Message = "Failed to extract activity context in format: '{0}', context: '{1}'.", Level = EventLevel.Warning)] + public void FailedToExtractActivityContext(string format, string exception) + { + this.WriteEvent(1, format, exception); + } + + [Event(2, Message = "Failed to inject activity context in format: '{0}', context: '{1}'.", Level = EventLevel.Warning)] + public void FailedToInjectActivityContext(string format, string error) + { + this.WriteEvent(2, format, error); + } + } +} diff --git a/src/OpenTelemetry.Extensions.Propagators/README.md b/src/OpenTelemetry.Extensions.Propagators/README.md index 7f83aa3e7b9..9872c5ff1ac 100644 --- a/src/OpenTelemetry.Extensions.Propagators/README.md +++ b/src/OpenTelemetry.Extensions.Propagators/README.md @@ -43,6 +43,15 @@ Sdk.SetDefaultTextMapPropagator(new CompositeTextMapPropagator(new TextMapPropag })); ``` +## Troubleshooting + +This component uses an +[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource) +with the name "OpenTelemetry.Extensions.Propagators" for its internal logging. +Please refer to [SDK +troubleshooting](../OpenTelemetry/README.md#troubleshooting) for instructions on +seeing these internal logs. + ## References * [B3 (Zipkin) Context specification](https://github.com/openzipkin/b3-propagation) diff --git a/src/OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule/CHANGELOG.md index e01fb752f60..fbb62f7ebbc 100644 --- a/src/OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + ## 1.0.0-rc9.3 Released 2022-Apr-15 diff --git a/src/OpenTelemetry.Instrumentation.AspNet/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.AspNet/CHANGELOG.md index e2e3dd4f641..9f6c1880f32 100644 --- a/src/OpenTelemetry.Instrumentation.AspNet/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.AspNet/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + ## 1.0.0-rc9.3 Released 2022-Apr-15 diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md index a9bb5ced3fa..66e2bf0f8bc 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + * Added additional metric dimensions. ([3247](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3247)) diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md index 4085ea49f92..8b25cf20d74 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + * Add `netstandard2.0` target enabling the Grpc.Net.Client instrumentation to be consumed by .NET Framework applications. ([#3105](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3105)) diff --git a/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md index 4972aa5cbf2..bcdbd2972fb 100644 --- a/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + ## 1.0.0-rc9.3 Released 2022-Apr-15 diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md index 908a894f68d..c74d54c0934 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + ## 1.0.0-rc9.3 Released 2022-Apr-15 diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Unshipped.txt deleted file mode 100644 index ebca0c81e02..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/net462/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,10 +0,0 @@ -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.set -> void -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.FlushInterval.get -> System.TimeSpan -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.FlushInterval.set -> void -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.SetVerboseDatabaseStatements.get -> bool -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.SetVerboseDatabaseStatements.set -> void -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.StackExchangeRedisCallsInstrumentationOptions() -> void -OpenTelemetry.Trace.TracerProviderBuilderExtensions -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, StackExchange.Redis.IConnectionMultiplexer connection = null, System.Action configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt deleted file mode 100644 index ebca0c81e02..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,10 +0,0 @@ -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.Enrich.set -> void -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.FlushInterval.get -> System.TimeSpan -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.FlushInterval.set -> void -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.SetVerboseDatabaseStatements.get -> bool -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.SetVerboseDatabaseStatements.set -> void -OpenTelemetry.Instrumentation.StackExchangeRedis.StackExchangeRedisCallsInstrumentationOptions.StackExchangeRedisCallsInstrumentationOptions() -> void -OpenTelemetry.Trace.TracerProviderBuilderExtensions -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddRedisInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, StackExchange.Redis.IConnectionMultiplexer connection = null, System.Action configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/AssemblyInfo.cs b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/AssemblyInfo.cs deleted file mode 100644 index b5227c02e19..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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. -// - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("OpenTelemetry.Instrumentation.StackExchangeRedis.Tests" + AssemblyInfo.PublicKey)] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)] - -#if SIGNED -internal static class AssemblyInfo -{ - public const string PublicKey = ", PublicKey=002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898"; - public const string MoqPublicKey = ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7"; -} -#else -internal static class AssemblyInfo -{ - public const string PublicKey = ""; - public const string MoqPublicKey = ""; -} -#endif diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/CHANGELOG.md deleted file mode 100644 index 348502a14dd..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/CHANGELOG.md +++ /dev/null @@ -1,109 +0,0 @@ -# Changelog - -## Unreleased - -## 1.0.0-rc9.3 - -Released 2022-Apr-15 - -* Removes .NET Framework 4.6.1. The minimum .NET Framework version supported is - .NET 4.6.2. - ([#3190](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3190)) - -* Bumped minimum required version of `Microsoft.Extensions.Options` to 3.1.0. - ([#2582](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3196)) - -## 1.0.0-rc9.2 - -Released 2022-Apr-12 - -## 1.0.0-rc9.1 - -Released 2022-Mar-30 - -## 1.0.0-rc10 (broken. use 1.0.0-rc9.1 and newer) - -Released 2022-Mar-04 - -## 1.0.0-rc9 - -Released 2022-Feb-02 - -## 1.0.0-rc8 - -Released 2021-Oct-08 - -* Adds SetVerboseDatabaseStatements option to allow setting more detailed - database statement tag values. -* Adds Enrich option to allow enriching activities from the source profiled - command objects. -* Removes upper constraint for Microsoft.Extensions.Options dependency. - ([#2179](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2179)) - -## 1.0.0-rc7 - -Released 2021-Jul-12 - -## 1.0.0-rc6 - -Released 2021-Jun-25 - -* `AddRedisInstrumentation` extension will now resolve `IConnectionMultiplexer` - & `StackExchangeRedisCallsInstrumentationOptions` through DI when - OpenTelemetry.Extensions.Hosting is in use. - ([#2110](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2110)) - -## 1.0.0-rc5 - -Released 2021-Jun-09 - -## 1.0.0-rc4 - -Released 2021-Apr-23 - -* Activities are now created with the `db.system` attribute set for usage during - sampling. - ([#1984](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1984)) - -## 1.0.0-rc3 - -Released 2021-Mar-19 - -## 1.0.0-rc2 - -Released 2021-Jan-29 - -## 1.0.0-rc1.1 - -Released 2020-Nov-17 - -## 0.8.0-beta.1 - -Released 2020-Nov-5 - -## 0.7.0-beta.1 - -Released 2020-Oct-16 - -* Span Status is populated as per new spec - ([#1313](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1313)) - -## 0.6.0-beta.1 - -Released 2020-Sep-15 - -## 0.5.0-beta.2 - -Released 2020-08-28 - -## 0.4.0-beta.2 - -Released 2020-07-24 - -* First beta release - -## 0.3.0-beta - -Released 2020-07-23 - -* Initial release diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/Implementation/RedisProfilerEntryToActivityConverter.cs b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/Implementation/RedisProfilerEntryToActivityConverter.cs deleted file mode 100644 index 9c821ab47b1..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/Implementation/RedisProfilerEntryToActivityConverter.cs +++ /dev/null @@ -1,209 +0,0 @@ -// -// 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. -// -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Net; -using System.Reflection; -using System.Reflection.Emit; -using OpenTelemetry.Trace; -using StackExchange.Redis.Profiling; - -namespace OpenTelemetry.Instrumentation.StackExchangeRedis.Implementation -{ - internal static class RedisProfilerEntryToActivityConverter - { - private static readonly Lazy> MessageDataGetter = new(() => - { - var redisAssembly = typeof(IProfiledCommand).Assembly; - Type profiledCommandType = redisAssembly.GetType("StackExchange.Redis.Profiling.ProfiledCommand"); - Type messageType = redisAssembly.GetType("StackExchange.Redis.Message"); - Type scriptMessageType = redisAssembly.GetType("StackExchange.Redis.RedisDatabase+ScriptEvalMessage"); - - var messageDelegate = CreateFieldGetter(profiledCommandType, "Message", BindingFlags.NonPublic | BindingFlags.Instance); - var scriptDelegate = CreateFieldGetter(scriptMessageType, "script", BindingFlags.NonPublic | BindingFlags.Instance); - var commandAndKeyFetcher = new PropertyFetcher("CommandAndKey"); - - if (messageDelegate == null) - { - return new Func(source => (null, null)); - } - - return new Func(source => - { - if (source == null) - { - return (null, null); - } - - var message = messageDelegate(source); - if (message == null) - { - return (null, null); - } - - string script = null; - if (message.GetType() == scriptMessageType) - { - script = scriptDelegate.Invoke(message); - } - - if (commandAndKeyFetcher.TryFetch(message, out var value)) - { - return (value, script); - } - - return (null, script); - }); - }); - - public static Activity ProfilerCommandToActivity(Activity parentActivity, IProfiledCommand command, StackExchangeRedisCallsInstrumentationOptions options) - { - var name = command.Command; // Example: SET; - if (string.IsNullOrEmpty(name)) - { - name = StackExchangeRedisCallsInstrumentation.ActivityName; - } - - var activity = StackExchangeRedisCallsInstrumentation.ActivitySource.StartActivity( - name, - ActivityKind.Client, - parentActivity?.Context ?? default, - StackExchangeRedisCallsInstrumentation.CreationTags, - startTime: command.CommandCreated); - - if (activity == null) - { - return null; - } - - activity.SetEndTime(command.CommandCreated + command.ElapsedTime); - - if (activity.IsAllDataRequested == true) - { - // see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/database.md - - // Timing example: - // command.CommandCreated; //2019-01-10 22:18:28Z - - // command.CreationToEnqueued; // 00:00:32.4571995 - // command.EnqueuedToSending; // 00:00:00.0352838 - // command.SentToResponse; // 00:00:00.0060586 - // command.ResponseToCompletion; // 00:00:00.0002601 - - // Total: - // command.ElapsedTime; // 00:00:32.4988020 - - activity.SetStatus(Status.Unset); - - activity.SetTag(StackExchangeRedisCallsInstrumentation.RedisFlagsKeyName, command.Flags.ToString()); - - if (options.SetVerboseDatabaseStatements) - { - var (commandAndKey, script) = MessageDataGetter.Value.Invoke(command); - - if (!string.IsNullOrEmpty(commandAndKey) && !string.IsNullOrEmpty(script)) - { - activity.SetTag(SemanticConventions.AttributeDbStatement, commandAndKey + " " + script); - } - else if (!string.IsNullOrEmpty(commandAndKey)) - { - activity.SetTag(SemanticConventions.AttributeDbStatement, commandAndKey); - } - else if (command.Command != null) - { - // Example: "db.statement": SET; - activity.SetTag(SemanticConventions.AttributeDbStatement, command.Command); - } - } - else if (command.Command != null) - { - // Example: "db.statement": SET; - activity.SetTag(SemanticConventions.AttributeDbStatement, command.Command); - } - - if (command.EndPoint != null) - { - if (command.EndPoint is IPEndPoint ipEndPoint) - { - activity.SetTag(SemanticConventions.AttributeNetPeerIp, ipEndPoint.Address.ToString()); - activity.SetTag(SemanticConventions.AttributeNetPeerPort, ipEndPoint.Port); - } - else if (command.EndPoint is DnsEndPoint dnsEndPoint) - { - activity.SetTag(SemanticConventions.AttributeNetPeerName, dnsEndPoint.Host); - activity.SetTag(SemanticConventions.AttributeNetPeerPort, dnsEndPoint.Port); - } - else - { - activity.SetTag(SemanticConventions.AttributePeerService, command.EndPoint.ToString()); - } - } - - activity.SetTag(StackExchangeRedisCallsInstrumentation.RedisDatabaseIndexKeyName, command.Db); - - // TODO: deal with the re-transmission - // command.RetransmissionOf; - // command.RetransmissionReason; - - var enqueued = command.CommandCreated.Add(command.CreationToEnqueued); - var send = enqueued.Add(command.EnqueuedToSending); - var response = send.Add(command.SentToResponse); - - activity.AddEvent(new ActivityEvent("Enqueued", enqueued)); - activity.AddEvent(new ActivityEvent("Sent", send)); - activity.AddEvent(new ActivityEvent("ResponseReceived", response)); - - options.Enrich?.Invoke(activity, command); - } - - activity.Stop(); - - return activity; - } - - public static void DrainSession(Activity parentActivity, IEnumerable sessionCommands, StackExchangeRedisCallsInstrumentationOptions options) - { - foreach (var command in sessionCommands) - { - ProfilerCommandToActivity(parentActivity, command, options); - } - } - - /// - /// Creates getter for a field defined in private or internal type - /// repesented with classType variable. - /// - private static Func CreateFieldGetter(Type classType, string fieldName, BindingFlags flags) - { - FieldInfo field = classType.GetField(fieldName, flags); - if (field != null) - { - string methodName = classType.FullName + ".get_" + field.Name; - DynamicMethod getterMethod = new DynamicMethod(methodName, typeof(TField), new[] { typeof(object) }, true); - ILGenerator generator = getterMethod.GetILGenerator(); - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Castclass, classType); - generator.Emit(OpCodes.Ldfld, field); - generator.Emit(OpCodes.Ret); - - return (Func)getterMethod.CreateDelegate(typeof(Func)); - } - - return null; - } - } -} diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/OpenTelemetry.Instrumentation.StackExchangeRedis.csproj b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/OpenTelemetry.Instrumentation.StackExchangeRedis.csproj deleted file mode 100644 index 1457194ac32..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/OpenTelemetry.Instrumentation.StackExchangeRedis.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - netstandard2.0;net462 - StackExchange.Redis instrumentation for OpenTelemetry .NET - $(PackageTags);distributed-tracing;Redis;StackExchange.Redis - true - true - - - - - - - - - - - - - - diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md deleted file mode 100644 index 5b109755fb2..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# StackExchange.Redis Instrumentation for OpenTelemetry - -[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Instrumentation.StackExchangeRedis.svg)](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.StackExchangeRedis) -[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Instrumentation.StackExchangeRedis.svg)](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.StackExchangeRedis) - -This is an -[Instrumentation Library](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library), -which instruments -[StackExchange.Redis](https://www.nuget.org/packages/StackExchange.Redis/) -and collects traces about outgoing calls to Redis. - -**Note: This component is based on the OpenTelemetry semantic conventions for -[traces](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/trace/semantic_conventions). -These conventions are -[Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/document-status.md), -and hence, this package is a [pre-release](../../VERSIONING.md#pre-releases). -Until a [stable -version](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/telemetry-stability.md) -is released, there can be breaking changes. You can track the progress from -[milestones](https://github.com/open-telemetry/opentelemetry-dotnet/milestone/23).** - -## Steps to enable OpenTelemetry.Instrumentation.StackExchangeRedis - -## Step 1: Install Package - -Add a reference to the -[`OpenTelemetry.Instrumentation.StackExchangeRedis`](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.StackExchangeRedis) -package. Also, add any other instrumentations & exporters you will need. - -```shell -dotnet add package OpenTelemetry.Instrumentation.StackExchangeRedis -``` - -## Step 2: Enable StackExchange.Redis Instrumentation at application startup - -StackExchange.Redis instrumentation must be enabled at application startup. -`AddRedisInstrumentation` method on `TracerProviderBuilder` must be called to -enable Redis instrumentation, passing the `IConnectionMultiplexer` instance used -to make Redis calls. Only those Redis calls made using the same instance of the -`IConnectionMultiplexer` will be instrumented. - -The following example demonstrates adding StackExchange.Redis instrumentation to -a console application. This example also sets up the OpenTelemetry Console -exporter, which requires adding the package -[`OpenTelemetry.Exporter.Console`](../OpenTelemetry.Exporter.Console/README.md) -to the application. - -```csharp -using OpenTelemetry.Trace; - -public class Program -{ - public static void Main(string[] args) - { - // Connect to the server. - using var connection = ConnectionMultiplexer.Connect("localhost:6379"); - - using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddRedisInstrumentation(connection) - .AddConsoleExporter() - .Build(); - } -} -``` - -For an ASP.NET Core application, adding instrumentation is typically done in -the `ConfigureServices` of your `Startup` class. Refer to documentation for -[OpenTelemetry.Instrumentation.AspNetCore](../OpenTelemetry.Instrumentation.AspNetCore/README.md). - -For an ASP.NET application, adding instrumentation is typically done in the -`Global.asax.cs`. Refer to documentation for [OpenTelemetry.Instrumentation.AspNet](../OpenTelemetry.Instrumentation.AspNet/README.md). - -## Advanced configuration - -This instrumentation can be configured to change the default behavior by using -`StackExchangeRedisCallsInstrumentationOptions`. - -### FlushInterval - -StackExchange.Redis has its own internal profiler. OpenTelemetry converts each -profiled command from the internal profiler to an Activity for collection. By -default, this conversion process flushes profiled commands on a 10 second -interval. The `FlushInterval` option can be used to adjust this interval. - -The following example shows how to use `FlushInterval`. - -```csharp -using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddRedisInstrumentation( - connection, - options => options.FlushInterval = TimeSpan.FromSeconds(5)) - .AddConsoleExporter() - .Build(); -``` - -### SetVerboseDatabaseStatements - -StackExchange.Redis by default does not give detailed database statements like -what key or script was used during an operation. The `SetVerboseDatabaseStatements` -option can be used to enable gathering this more detailed information. - -The following example shows how to use `SetVerboseDatabaseStatements`. - -```csharp -using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddRedisInstrumentation( - connection, - options => options.SetVerboseDatabaseStatements = true) - .AddConsoleExporter() - .Build(); -``` - -## Enrich - -This option allows one to enrich the activity with additional information from the -raw `IProfiledCommand` object. The `Enrich` action is called only when -`activity.IsAllDataRequested` is `true`. It contains the activity itself (which can -be enriched), and the source profiled command object. - -The following code snippet shows how to add additional tags using `Enrich`. - -```csharp -using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddRedisInstrumentation(opt => opt.Enrich = (activity, command) => - { - if (command.ElapsedTime < TimeSpan.FromMilliseconds(100)) - { - activity.SetTag("is_fast", true); - } - }) - .Build(); -``` - -## References - -* [OpenTelemetry Project](https://opentelemetry.io/) -* [StackExchange.Redis Profiling](https://stackexchange.github.io/StackExchange.Redis/Profiling_v1.html) diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentation.cs b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentation.cs deleted file mode 100644 index 6c5a1ed1ae0..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentation.cs +++ /dev/null @@ -1,151 +0,0 @@ -// -// 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. -// - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; -using OpenTelemetry.Instrumentation.StackExchangeRedis.Implementation; -using OpenTelemetry.Internal; -using OpenTelemetry.Trace; -using StackExchange.Redis; -using StackExchange.Redis.Profiling; - -namespace OpenTelemetry.Instrumentation.StackExchangeRedis -{ - /// - /// Redis calls instrumentation. - /// - internal class StackExchangeRedisCallsInstrumentation : IDisposable - { - internal const string RedisDatabaseIndexKeyName = "db.redis.database_index"; - internal const string RedisFlagsKeyName = "db.redis.flags"; - internal const string ActivitySourceName = "OpenTelemetry.StackExchange.Redis"; - internal const string ActivityName = ActivitySourceName + ".Execute"; - internal static readonly Version Version = typeof(StackExchangeRedisCallsInstrumentation).Assembly.GetName().Version; - internal static readonly ActivitySource ActivitySource = new(ActivitySourceName, Version.ToString()); - internal static readonly IEnumerable> CreationTags = new[] - { - new KeyValuePair(SemanticConventions.AttributeDbSystem, "redis"), - }; - - internal readonly ConcurrentDictionary<(ActivityTraceId TraceId, ActivitySpanId SpanId), (Activity Activity, ProfilingSession Session)> Cache - = new(); - - private readonly StackExchangeRedisCallsInstrumentationOptions options; - private readonly EventWaitHandle stopHandle = new(false, EventResetMode.ManualReset); - private readonly Thread drainThread; - - private readonly ProfilingSession defaultSession = new(); - - /// - /// Initializes a new instance of the class. - /// - /// to instrument. - /// Configuration options for redis instrumentation. - public StackExchangeRedisCallsInstrumentation(IConnectionMultiplexer connection, StackExchangeRedisCallsInstrumentationOptions options) - { - Guard.ThrowIfNull(connection); - - this.options = options ?? new StackExchangeRedisCallsInstrumentationOptions(); - - this.drainThread = new Thread(this.DrainEntries) - { - Name = "OpenTelemetry.Redis", - }; - this.drainThread.Start(); - - connection.RegisterProfiler(this.GetProfilerSessionsFactory()); - } - - /// - /// Returns session for the Redis calls recording. - /// - /// Session associated with the current span context to record Redis calls. - public Func GetProfilerSessionsFactory() - { - return () => - { - if (this.stopHandle.WaitOne(0)) - { - return null; - } - - Activity parent = Activity.Current; - - // If no parent use the default session. - if (parent == null || parent.IdFormat != ActivityIdFormat.W3C) - { - return this.defaultSession; - } - - // Try to reuse a session for all activities created under the same TraceId+SpanId. - var cacheKey = (parent.TraceId, parent.SpanId); - if (!this.Cache.TryGetValue(cacheKey, out var session)) - { - session = (parent, new ProfilingSession()); - this.Cache.TryAdd(cacheKey, session); - } - - return session.Session; - }; - } - - /// - public void Dispose() - { - this.stopHandle.Set(); - this.drainThread.Join(); - - this.Flush(); - - this.stopHandle.Dispose(); - } - - internal void Flush() - { - RedisProfilerEntryToActivityConverter.DrainSession(null, this.defaultSession.FinishProfiling(), this.options); - - foreach (var entry in this.Cache) - { - var parent = entry.Value.Activity; - if (parent.Duration == TimeSpan.Zero) - { - // Activity is still running, don't drain. - continue; - } - - ProfilingSession session = entry.Value.Session; - RedisProfilerEntryToActivityConverter.DrainSession(parent, session.FinishProfiling(), this.options); - this.Cache.TryRemove((entry.Key.TraceId, entry.Key.SpanId), out _); - } - } - - private void DrainEntries(object state) - { - while (true) - { - if (this.stopHandle.WaitOne(this.options.FlushInterval)) - { - break; - } - - this.Flush(); - } - } - } -} diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentationOptions.cs b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentationOptions.cs deleted file mode 100644 index ee32c511f0e..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/StackExchangeRedisCallsInstrumentationOptions.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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. -// - -using System; -using System.Diagnostics; -using OpenTelemetry.Trace; -using StackExchange.Redis.Profiling; - -namespace OpenTelemetry.Instrumentation.StackExchangeRedis -{ - /// - /// Options for StackExchange.Redis instrumentation. - /// - public class StackExchangeRedisCallsInstrumentationOptions - { - /// - /// Gets or sets the maximum time that should elapse between flushing the internal buffer of Redis profiling sessions and creating objects. Default value: 00:00:10. - /// - public TimeSpan FlushInterval { get; set; } = TimeSpan.FromSeconds(10); - - /// - /// Gets or sets a value indicating whether or not the should use reflection to get more detailed tag values. Default value: False. - /// - public bool SetVerboseDatabaseStatements { get; set; } - - /// - /// Gets or sets an action to enrich an Activity. - /// - /// - /// : the activity being enriched. - /// : the profiled redis command from which additional information can be extracted to enrich the activity. - /// - public Action Enrich { get; set; } - } -} diff --git a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/TracerProviderBuilderExtensions.cs b/src/OpenTelemetry.Instrumentation.StackExchangeRedis/TracerProviderBuilderExtensions.cs deleted file mode 100644 index e9aade22702..00000000000 --- a/src/OpenTelemetry.Instrumentation.StackExchangeRedis/TracerProviderBuilderExtensions.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// 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. -// - -using System; -using OpenTelemetry.Instrumentation.StackExchangeRedis; -using OpenTelemetry.Internal; -using StackExchange.Redis; - -namespace OpenTelemetry.Trace -{ - /// - /// Extension methods to simplify registering of dependency instrumentation. - /// - public static class TracerProviderBuilderExtensions - { - /// - /// Enables automatic data collection of outgoing requests to Redis. - /// - /// - /// Note: If an is not supplied - /// using the parameter it will be - /// resolved using the application . - /// - /// being configured. - /// Optional to instrument. - /// Optional callback to configure options. - /// The instance of to chain the calls. - public static TracerProviderBuilder AddRedisInstrumentation( - this TracerProviderBuilder builder, - IConnectionMultiplexer connection = null, - Action configure = null) - { - Guard.ThrowIfNull(builder); - - if (builder is not IDeferredTracerProviderBuilder deferredTracerProviderBuilder) - { - if (connection == null) - { - throw new NotSupportedException($"StackExchange.Redis {nameof(IConnectionMultiplexer)} must be supplied when dependency injection is unavailable - to enable dependency injection use the OpenTelemetry.Extensions.Hosting package"); - } - - return AddRedisInstrumentation(builder, connection, new StackExchangeRedisCallsInstrumentationOptions(), configure); - } - - return deferredTracerProviderBuilder.Configure((sp, builder) => - { - if (connection == null) - { - connection = (IConnectionMultiplexer)sp.GetService(typeof(IConnectionMultiplexer)); - if (connection == null) - { - throw new InvalidOperationException($"StackExchange.Redis {nameof(IConnectionMultiplexer)} could not be resolved through application {nameof(IServiceProvider)}"); - } - } - - AddRedisInstrumentation( - builder, - connection, - sp.GetOptions(), - configure); - }); - } - - private static TracerProviderBuilder AddRedisInstrumentation( - TracerProviderBuilder builder, - IConnectionMultiplexer connection, - StackExchangeRedisCallsInstrumentationOptions options, - Action configure = null) - { - configure?.Invoke(options); - - return builder - .AddInstrumentation(() => new StackExchangeRedisCallsInstrumentation(connection, options)) - .AddSource(StackExchangeRedisCallsInstrumentation.ActivitySourceName); - } - } -} diff --git a/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md b/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md index 64c4687135a..30a4b655820 100644 --- a/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md +++ b/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.4 + +Released 2022-Jun-03 + * Removes .NET Framework 4.6.1. The minimum .NET Framework version supported is .NET 4.6.2. ([#3190](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3190)) diff --git a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt index 8b30b3a9d50..56774a7fc4d 100644 --- a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt @@ -1,39 +1,131 @@ #nullable enable ~abstract OpenTelemetry.BaseExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult ~abstract OpenTelemetry.BaseExportProcessor.OnExport(T data) -> void +~OpenTelemetry.BaseExporter +~OpenTelemetry.BaseExporter.ParentProvider.get -> OpenTelemetry.BaseProvider +~OpenTelemetry.BaseExportProcessor +~OpenTelemetry.BaseExportProcessor.BaseExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.BaseProcessor.ParentProvider.get -> OpenTelemetry.BaseProvider +~OpenTelemetry.Batch +~OpenTelemetry.Batch.Batch(T[] items, int count) -> void +~OpenTelemetry.Batch.Enumerator.Current.get -> T +~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator +~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +~OpenTelemetry.BatchExportProcessor +~OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +~OpenTelemetry.BatchExportProcessorOptions +~OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.CompositeProcessor +~OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable> processors) -> void +~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.get -> double[] +~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.set -> void +~OpenTelemetry.Metrics.IPullMetricExporter.Collect.get -> System.Func +~OpenTelemetry.Metrics.IPullMetricExporter.Collect.set -> void +~OpenTelemetry.Metrics.MeterProviderBuilderBase.Build() -> OpenTelemetry.Metrics.MeterProvider +~OpenTelemetry.Metrics.Metric.Description.get -> string +~OpenTelemetry.Metrics.Metric.MeterName.get -> string +~OpenTelemetry.Metrics.Metric.MeterVersion.get -> string +~OpenTelemetry.Metrics.Metric.Name.get -> string +~OpenTelemetry.Metrics.Metric.Unit.get -> string +~OpenTelemetry.Metrics.MetricPoint.GetHistogramBuckets() -> OpenTelemetry.Metrics.HistogramBuckets +~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.get -> OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions +~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.set -> void +~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.get -> string +~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.set -> void +~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.get -> string +~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.set -> void +~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] +~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void +~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void +~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource +~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void +~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder +~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource +~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder +~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.SimpleExportProcessor +~OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void +~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void +~OpenTelemetry.Trace.Sampler.Description.get -> string +~OpenTelemetry.Trace.Sampler.Description.set -> void +~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable +~OpenTelemetry.Trace.SamplingParameters.Name.get -> string +~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void +~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void +~OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider +~override OpenTelemetry.BaseExportProcessor.OnEnd(T data) -> void +~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +~override OpenTelemetry.BatchExportProcessor.OnExport(T data) -> void +~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder +~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder +~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +~override OpenTelemetry.SimpleExportProcessor.OnExport(T data) -> void +~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool +~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +~override sealed OpenTelemetry.BaseExportProcessor.OnStart(T data) -> void +~readonly OpenTelemetry.BaseExportProcessor.exporter -> OpenTelemetry.BaseExporter +~readonly OpenTelemetry.Metrics.BaseExportingMetricReader.exporter -> OpenTelemetry.BaseExporter +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Metrics.MetricReader reader) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, OpenTelemetry.Metrics.MetricStreamConfiguration metricStreamConfiguration) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, string name) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Func viewConfig) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProvider +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricPointsPerMetricStream(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricStreams(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricStreams) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderExtensions.ForceFlush(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool +~static OpenTelemetry.Metrics.MeterProviderExtensions.Shutdown(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool +~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration +~static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource +~static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource +~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource +~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator textMapPropagator) -> void +~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Trace.Sampler sampler) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProvider +~static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool +~static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool abstract OpenTelemetry.Trace.Sampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions -~OpenTelemetry.BaseExporter OpenTelemetry.BaseExporter.BaseExporter() -> void OpenTelemetry.BaseExporter.Dispose() -> void OpenTelemetry.BaseExporter.ForceFlush(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.BaseExporter.ParentProvider.get -> OpenTelemetry.BaseProvider OpenTelemetry.BaseExporter.Shutdown(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.BaseExportProcessor -~OpenTelemetry.BaseExportProcessor.BaseExportProcessor(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.BaseProcessor OpenTelemetry.BaseProcessor.BaseProcessor() -> void OpenTelemetry.BaseProcessor.Dispose() -> void OpenTelemetry.BaseProcessor.ForceFlush(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.BaseProcessor.ParentProvider.get -> OpenTelemetry.BaseProvider OpenTelemetry.BaseProcessor.Shutdown(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.Batch OpenTelemetry.Batch.Batch() -> void -~OpenTelemetry.Batch.Batch(T[] items, int count) -> void OpenTelemetry.Batch.Count.get -> long OpenTelemetry.Batch.Dispose() -> void OpenTelemetry.Batch.Enumerator -~OpenTelemetry.Batch.Enumerator.Current.get -> T OpenTelemetry.Batch.Enumerator.Dispose() -> void OpenTelemetry.Batch.Enumerator.Enumerator() -> void OpenTelemetry.Batch.Enumerator.MoveNext() -> bool OpenTelemetry.Batch.Enumerator.Reset() -> void -~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator OpenTelemetry.BatchActivityExportProcessor -~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessor -~OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessorOptions OpenTelemetry.BatchExportProcessorOptions.BatchExportProcessorOptions() -> void OpenTelemetry.BatchExportProcessorOptions.ExporterTimeoutMilliseconds.get -> int OpenTelemetry.BatchExportProcessorOptions.ExporterTimeoutMilliseconds.set -> void @@ -46,8 +138,6 @@ OpenTelemetry.BatchExportProcessorOptions.ScheduledDelayMilliseconds.set -> v OpenTelemetry.BatchLogRecordExportProcessor OpenTelemetry.BatchLogRecordExportProcessor.BatchLogRecordExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void OpenTelemetry.CompositeProcessor -~OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.CompositeProcessor -~OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable> processors) -> void OpenTelemetry.ExportProcessorType OpenTelemetry.ExportProcessorType.Batch = 1 -> OpenTelemetry.ExportProcessorType OpenTelemetry.ExportProcessorType.Simple = 0 -> OpenTelemetry.ExportProcessorType @@ -60,10 +150,13 @@ OpenTelemetry.Logs.LogRecord.EventId.get -> Microsoft.Extensions.Logging.EventId OpenTelemetry.Logs.LogRecord.Exception.get -> System.Exception? OpenTelemetry.Logs.LogRecord.ForEachScope(System.Action! callback, TState state) -> void OpenTelemetry.Logs.LogRecord.FormattedMessage.get -> string? +OpenTelemetry.Logs.LogRecord.FormattedMessage.set -> void OpenTelemetry.Logs.LogRecord.LogLevel.get -> Microsoft.Extensions.Logging.LogLevel OpenTelemetry.Logs.LogRecord.SpanId.get -> System.Diagnostics.ActivitySpanId OpenTelemetry.Logs.LogRecord.State.get -> object? +OpenTelemetry.Logs.LogRecord.State.set -> void OpenTelemetry.Logs.LogRecord.StateValues.get -> System.Collections.Generic.IReadOnlyList>? +OpenTelemetry.Logs.LogRecord.StateValues.set -> void OpenTelemetry.Logs.LogRecord.Timestamp.get -> System.DateTime OpenTelemetry.Logs.LogRecord.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags OpenTelemetry.Logs.LogRecord.TraceId.get -> System.Diagnostics.ActivityTraceId @@ -96,11 +189,8 @@ OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Cumulative = 1 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Delta = 2 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.BaseExportingMetricReader -~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.Metrics.BaseExportingMetricReader.SupportedExportModes.get -> OpenTelemetry.Metrics.ExportModes OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration -~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.get -> double[] -~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.set -> void OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.ExplicitBucketHistogramConfiguration() -> void OpenTelemetry.Metrics.ExportModes OpenTelemetry.Metrics.ExportModes.Pull = 2 -> OpenTelemetry.Metrics.ExportModes @@ -119,27 +209,18 @@ OpenTelemetry.Metrics.HistogramBuckets.Enumerator.Enumerator() -> void OpenTelemetry.Metrics.HistogramBuckets.Enumerator.MoveNext() -> bool OpenTelemetry.Metrics.HistogramBuckets.GetEnumerator() -> OpenTelemetry.Metrics.HistogramBuckets.Enumerator OpenTelemetry.Metrics.IPullMetricExporter -~OpenTelemetry.Metrics.IPullMetricExporter.Collect.get -> System.Func -~OpenTelemetry.Metrics.IPullMetricExporter.Collect.set -> void OpenTelemetry.Metrics.MeterProviderBuilderBase -~OpenTelemetry.Metrics.MeterProviderBuilderBase.Build() -> OpenTelemetry.Metrics.MeterProvider OpenTelemetry.Metrics.MeterProviderBuilderBase.MeterProviderBuilderBase() -> void OpenTelemetry.Metrics.MeterProviderBuilderExtensions OpenTelemetry.Metrics.MeterProviderExtensions OpenTelemetry.Metrics.Metric -~OpenTelemetry.Metrics.Metric.Description.get -> string OpenTelemetry.Metrics.Metric.GetMetricPoints() -> OpenTelemetry.Metrics.MetricPointsAccessor -~OpenTelemetry.Metrics.Metric.MeterName.get -> string -~OpenTelemetry.Metrics.Metric.MeterVersion.get -> string OpenTelemetry.Metrics.Metric.MetricType.get -> OpenTelemetry.Metrics.MetricType -~OpenTelemetry.Metrics.Metric.Name.get -> string OpenTelemetry.Metrics.Metric.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality -~OpenTelemetry.Metrics.Metric.Unit.get -> string OpenTelemetry.Metrics.MetricPoint OpenTelemetry.Metrics.MetricPoint.EndTime.get -> System.DateTimeOffset OpenTelemetry.Metrics.MetricPoint.GetGaugeLastValueDouble() -> double OpenTelemetry.Metrics.MetricPoint.GetGaugeLastValueLong() -> long -~OpenTelemetry.Metrics.MetricPoint.GetHistogramBuckets() -> OpenTelemetry.Metrics.HistogramBuckets OpenTelemetry.Metrics.MetricPoint.GetHistogramCount() -> long OpenTelemetry.Metrics.MetricPoint.GetHistogramSum() -> double OpenTelemetry.Metrics.MetricPoint.GetSumDouble() -> double @@ -163,21 +244,13 @@ OpenTelemetry.Metrics.MetricReader.TemporalityPreference.get -> OpenTelemetry.Me OpenTelemetry.Metrics.MetricReader.TemporalityPreference.set -> void OpenTelemetry.Metrics.MetricReaderOptions OpenTelemetry.Metrics.MetricReaderOptions.MetricReaderOptions() -> void -~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.get -> OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions -~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.set -> void OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.get -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.set -> void OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Cumulative = 1 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Delta = 2 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricStreamConfiguration -~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.get -> string -~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.set -> void OpenTelemetry.Metrics.MetricStreamConfiguration.MetricStreamConfiguration() -> void -~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.get -> string -~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.set -> void -~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] -~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void OpenTelemetry.Metrics.MetricType OpenTelemetry.Metrics.MetricType.DoubleGauge = 45 -> OpenTelemetry.Metrics.MetricType OpenTelemetry.Metrics.MetricType.DoubleSum = 29 -> OpenTelemetry.Metrics.MetricType @@ -186,7 +259,6 @@ OpenTelemetry.Metrics.MetricType.LongGauge = 42 -> OpenTelemetry.Metrics.MetricT OpenTelemetry.Metrics.MetricType.LongSum = 26 -> OpenTelemetry.Metrics.MetricType OpenTelemetry.Metrics.MetricTypeExtensions OpenTelemetry.Metrics.PeriodicExportingMetricReader -~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.get -> int? OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.set -> void @@ -197,27 +269,16 @@ OpenTelemetry.ProviderExtensions OpenTelemetry.ReadOnlyTagCollection OpenTelemetry.ReadOnlyTagCollection.Count.get -> int OpenTelemetry.ReadOnlyTagCollection.Enumerator -~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair OpenTelemetry.ReadOnlyTagCollection.Enumerator.Enumerator() -> void OpenTelemetry.ReadOnlyTagCollection.Enumerator.MoveNext() -> bool OpenTelemetry.ReadOnlyTagCollection.GetEnumerator() -> OpenTelemetry.ReadOnlyTagCollection.Enumerator OpenTelemetry.ReadOnlyTagCollection.ReadOnlyTagCollection() -> void OpenTelemetry.Resources.IResourceDetector -~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder OpenTelemetry.Resources.ResourceBuilderExtensions OpenTelemetry.Sdk OpenTelemetry.SimpleActivityExportProcessor -~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void -~OpenTelemetry.SimpleExportProcessor -~OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.SimpleLogRecordExportProcessor OpenTelemetry.SimpleLogRecordExportProcessor.SimpleLogRecordExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void OpenTelemetry.SuppressInstrumentationScope @@ -229,11 +290,7 @@ OpenTelemetry.Trace.AlwaysOnSampler.AlwaysOnSampler() -> void OpenTelemetry.Trace.BatchExportActivityProcessorOptions OpenTelemetry.Trace.BatchExportActivityProcessorOptions.BatchExportActivityProcessorOptions() -> void OpenTelemetry.Trace.ParentBasedSampler -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void OpenTelemetry.Trace.Sampler -~OpenTelemetry.Trace.Sampler.Description.get -> string -~OpenTelemetry.Trace.Sampler.Description.set -> void OpenTelemetry.Trace.Sampler.Sampler() -> void OpenTelemetry.Trace.SamplingDecision OpenTelemetry.Trace.SamplingDecision.Drop = 0 -> OpenTelemetry.Trace.SamplingDecision @@ -241,36 +298,25 @@ OpenTelemetry.Trace.SamplingDecision.RecordAndSample = 2 -> OpenTelemetry.Trace. OpenTelemetry.Trace.SamplingDecision.RecordOnly = 1 -> OpenTelemetry.Trace.SamplingDecision OpenTelemetry.Trace.SamplingParameters OpenTelemetry.Trace.SamplingParameters.Kind.get -> System.Diagnostics.ActivityKind -~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable -~OpenTelemetry.Trace.SamplingParameters.Name.get -> string OpenTelemetry.Trace.SamplingParameters.ParentContext.get -> System.Diagnostics.ActivityContext OpenTelemetry.Trace.SamplingParameters.SamplingParameters() -> void -~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void -~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.SamplingParameters.TraceId.get -> System.Diagnostics.ActivityTraceId OpenTelemetry.Trace.SamplingResult -~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.SamplingResult.Decision.get -> OpenTelemetry.Trace.SamplingDecision OpenTelemetry.Trace.SamplingResult.Equals(OpenTelemetry.Trace.SamplingResult other) -> bool OpenTelemetry.Trace.SamplingResult.SamplingResult() -> void OpenTelemetry.Trace.SamplingResult.SamplingResult(bool isSampled) -> void OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision) -> void -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void OpenTelemetry.Trace.TraceIdRatioBasedSampler OpenTelemetry.Trace.TraceIdRatioBasedSampler.TraceIdRatioBasedSampler(double probability) -> void OpenTelemetry.Trace.TracerProviderBuilderBase -~OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder -~OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider OpenTelemetry.Trace.TracerProviderBuilderBase.TracerProviderBuilderBase() -> void OpenTelemetry.Trace.TracerProviderBuilderExtensions OpenTelemetry.Trace.TracerProviderExtensions override OpenTelemetry.BaseExportProcessor.Dispose(bool disposing) -> void -~override OpenTelemetry.BaseExportProcessor.OnEnd(T data) -> void override OpenTelemetry.BaseExportProcessor.OnForceFlush(int timeoutMilliseconds) -> bool override OpenTelemetry.BaseExportProcessor.OnShutdown(int timeoutMilliseconds) -> bool -~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void override OpenTelemetry.BatchExportProcessor.Dispose(bool disposing) -> void -~override OpenTelemetry.BatchExportProcessor.OnExport(T data) -> void override OpenTelemetry.BatchExportProcessor.OnForceFlush(int timeoutMilliseconds) -> bool override OpenTelemetry.BatchExportProcessor.OnShutdown(int timeoutMilliseconds) -> bool override OpenTelemetry.BatchLogRecordExportProcessor.OnEnd(OpenTelemetry.Logs.LogRecord! data) -> void @@ -283,66 +329,23 @@ override OpenTelemetry.Logs.OpenTelemetryLoggerProvider.Dispose(bool disposing) override OpenTelemetry.Metrics.BaseExportingMetricReader.Dispose(bool disposing) -> void override OpenTelemetry.Metrics.BaseExportingMetricReader.OnCollect(int timeoutMilliseconds) -> bool override OpenTelemetry.Metrics.BaseExportingMetricReader.OnShutdown(int timeoutMilliseconds) -> bool -~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder -~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder override OpenTelemetry.Metrics.PeriodicExportingMetricReader.Dispose(bool disposing) -> void override OpenTelemetry.Metrics.PeriodicExportingMetricReader.OnShutdown(int timeoutMilliseconds) -> bool -~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void -~override OpenTelemetry.SimpleExportProcessor.OnExport(T data) -> void override OpenTelemetry.Trace.AlwaysOffSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult override OpenTelemetry.Trace.AlwaysOnSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult override OpenTelemetry.Trace.ParentBasedSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult -~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool override OpenTelemetry.Trace.SamplingResult.GetHashCode() -> int override OpenTelemetry.Trace.TraceIdRatioBasedSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult -~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder -~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder -~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder -~override sealed OpenTelemetry.BaseExportProcessor.OnStart(T data) -> void -~readonly OpenTelemetry.BaseExportProcessor.exporter -> OpenTelemetry.BaseExporter -~readonly OpenTelemetry.Metrics.BaseExportingMetricReader.exporter -> OpenTelemetry.BaseExporter static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder! -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Metrics.MetricReader reader) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, OpenTelemetry.Metrics.MetricStreamConfiguration metricStreamConfiguration) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, string name) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Func viewConfig) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProvider -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricPointsPerMetricStream(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricStreams(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricStreams) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderExtensions.ForceFlush(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool -~static OpenTelemetry.Metrics.MeterProviderExtensions.Shutdown(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool -~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration static OpenTelemetry.Metrics.MetricTypeExtensions.IsDouble(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsGauge(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsHistogram(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsLong(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsSum(this OpenTelemetry.Metrics.MetricType self) -> bool -~static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator textMapPropagator) -> void static OpenTelemetry.Sdk.SuppressInstrumentation.get -> bool -~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable static OpenTelemetry.SuppressInstrumentationScope.Enter() -> int static OpenTelemetry.Trace.SamplingResult.operator !=(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool static OpenTelemetry.Trace.SamplingResult.operator ==(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Trace.Sampler sampler) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProvider -~static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool -~static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool virtual OpenTelemetry.BaseExporter.Dispose(bool disposing) -> void virtual OpenTelemetry.BaseExporter.OnForceFlush(int timeoutMilliseconds) -> bool virtual OpenTelemetry.BaseExporter.OnShutdown(int timeoutMilliseconds) -> bool diff --git a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt index ff0d049a675..e69de29bb2d 100644 --- a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,4 +0,0 @@ -#nullable enable -OpenTelemetry.Logs.LogRecord.FormattedMessage.set -> void -OpenTelemetry.Logs.LogRecord.State.set -> void -OpenTelemetry.Logs.LogRecord.StateValues.set -> void diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt index 8b30b3a9d50..56774a7fc4d 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt @@ -1,39 +1,131 @@ #nullable enable ~abstract OpenTelemetry.BaseExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult ~abstract OpenTelemetry.BaseExportProcessor.OnExport(T data) -> void +~OpenTelemetry.BaseExporter +~OpenTelemetry.BaseExporter.ParentProvider.get -> OpenTelemetry.BaseProvider +~OpenTelemetry.BaseExportProcessor +~OpenTelemetry.BaseExportProcessor.BaseExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.BaseProcessor.ParentProvider.get -> OpenTelemetry.BaseProvider +~OpenTelemetry.Batch +~OpenTelemetry.Batch.Batch(T[] items, int count) -> void +~OpenTelemetry.Batch.Enumerator.Current.get -> T +~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator +~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +~OpenTelemetry.BatchExportProcessor +~OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +~OpenTelemetry.BatchExportProcessorOptions +~OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.CompositeProcessor +~OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable> processors) -> void +~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.get -> double[] +~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.set -> void +~OpenTelemetry.Metrics.IPullMetricExporter.Collect.get -> System.Func +~OpenTelemetry.Metrics.IPullMetricExporter.Collect.set -> void +~OpenTelemetry.Metrics.MeterProviderBuilderBase.Build() -> OpenTelemetry.Metrics.MeterProvider +~OpenTelemetry.Metrics.Metric.Description.get -> string +~OpenTelemetry.Metrics.Metric.MeterName.get -> string +~OpenTelemetry.Metrics.Metric.MeterVersion.get -> string +~OpenTelemetry.Metrics.Metric.Name.get -> string +~OpenTelemetry.Metrics.Metric.Unit.get -> string +~OpenTelemetry.Metrics.MetricPoint.GetHistogramBuckets() -> OpenTelemetry.Metrics.HistogramBuckets +~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.get -> OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions +~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.set -> void +~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.get -> string +~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.set -> void +~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.get -> string +~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.set -> void +~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] +~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void +~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void +~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource +~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource +~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void +~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder +~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource +~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder +~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.SimpleExportProcessor +~OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void +~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void +~OpenTelemetry.Trace.Sampler.Description.get -> string +~OpenTelemetry.Trace.Sampler.Description.set -> void +~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable +~OpenTelemetry.Trace.SamplingParameters.Name.get -> string +~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void +~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void +~OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider +~override OpenTelemetry.BaseExportProcessor.OnEnd(T data) -> void +~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +~override OpenTelemetry.BatchExportProcessor.OnExport(T data) -> void +~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder +~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder +~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +~override OpenTelemetry.SimpleExportProcessor.OnExport(T data) -> void +~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool +~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +~override sealed OpenTelemetry.BaseExportProcessor.OnStart(T data) -> void +~readonly OpenTelemetry.BaseExportProcessor.exporter -> OpenTelemetry.BaseExporter +~readonly OpenTelemetry.Metrics.BaseExportingMetricReader.exporter -> OpenTelemetry.BaseExporter +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Metrics.MetricReader reader) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, OpenTelemetry.Metrics.MetricStreamConfiguration metricStreamConfiguration) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, string name) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Func viewConfig) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProvider +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricPointsPerMetricStream(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricStreams(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricStreams) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Metrics.MeterProviderExtensions.ForceFlush(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool +~static OpenTelemetry.Metrics.MeterProviderExtensions.Shutdown(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool +~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration +~static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource +~static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource +~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource +~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +~static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder +~static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator textMapPropagator) -> void +~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Trace.Sampler sampler) -> OpenTelemetry.Trace.TracerProviderBuilder +~static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProvider +~static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool +~static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool abstract OpenTelemetry.Trace.Sampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions -~OpenTelemetry.BaseExporter OpenTelemetry.BaseExporter.BaseExporter() -> void OpenTelemetry.BaseExporter.Dispose() -> void OpenTelemetry.BaseExporter.ForceFlush(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.BaseExporter.ParentProvider.get -> OpenTelemetry.BaseProvider OpenTelemetry.BaseExporter.Shutdown(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.BaseExportProcessor -~OpenTelemetry.BaseExportProcessor.BaseExportProcessor(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.BaseProcessor OpenTelemetry.BaseProcessor.BaseProcessor() -> void OpenTelemetry.BaseProcessor.Dispose() -> void OpenTelemetry.BaseProcessor.ForceFlush(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.BaseProcessor.ParentProvider.get -> OpenTelemetry.BaseProvider OpenTelemetry.BaseProcessor.Shutdown(int timeoutMilliseconds = -1) -> bool -~OpenTelemetry.Batch OpenTelemetry.Batch.Batch() -> void -~OpenTelemetry.Batch.Batch(T[] items, int count) -> void OpenTelemetry.Batch.Count.get -> long OpenTelemetry.Batch.Dispose() -> void OpenTelemetry.Batch.Enumerator -~OpenTelemetry.Batch.Enumerator.Current.get -> T OpenTelemetry.Batch.Enumerator.Dispose() -> void OpenTelemetry.Batch.Enumerator.Enumerator() -> void OpenTelemetry.Batch.Enumerator.MoveNext() -> bool OpenTelemetry.Batch.Enumerator.Reset() -> void -~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator OpenTelemetry.BatchActivityExportProcessor -~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessor -~OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessorOptions OpenTelemetry.BatchExportProcessorOptions.BatchExportProcessorOptions() -> void OpenTelemetry.BatchExportProcessorOptions.ExporterTimeoutMilliseconds.get -> int OpenTelemetry.BatchExportProcessorOptions.ExporterTimeoutMilliseconds.set -> void @@ -46,8 +138,6 @@ OpenTelemetry.BatchExportProcessorOptions.ScheduledDelayMilliseconds.set -> v OpenTelemetry.BatchLogRecordExportProcessor OpenTelemetry.BatchLogRecordExportProcessor.BatchLogRecordExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void OpenTelemetry.CompositeProcessor -~OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.CompositeProcessor -~OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable> processors) -> void OpenTelemetry.ExportProcessorType OpenTelemetry.ExportProcessorType.Batch = 1 -> OpenTelemetry.ExportProcessorType OpenTelemetry.ExportProcessorType.Simple = 0 -> OpenTelemetry.ExportProcessorType @@ -60,10 +150,13 @@ OpenTelemetry.Logs.LogRecord.EventId.get -> Microsoft.Extensions.Logging.EventId OpenTelemetry.Logs.LogRecord.Exception.get -> System.Exception? OpenTelemetry.Logs.LogRecord.ForEachScope(System.Action! callback, TState state) -> void OpenTelemetry.Logs.LogRecord.FormattedMessage.get -> string? +OpenTelemetry.Logs.LogRecord.FormattedMessage.set -> void OpenTelemetry.Logs.LogRecord.LogLevel.get -> Microsoft.Extensions.Logging.LogLevel OpenTelemetry.Logs.LogRecord.SpanId.get -> System.Diagnostics.ActivitySpanId OpenTelemetry.Logs.LogRecord.State.get -> object? +OpenTelemetry.Logs.LogRecord.State.set -> void OpenTelemetry.Logs.LogRecord.StateValues.get -> System.Collections.Generic.IReadOnlyList>? +OpenTelemetry.Logs.LogRecord.StateValues.set -> void OpenTelemetry.Logs.LogRecord.Timestamp.get -> System.DateTime OpenTelemetry.Logs.LogRecord.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags OpenTelemetry.Logs.LogRecord.TraceId.get -> System.Diagnostics.ActivityTraceId @@ -96,11 +189,8 @@ OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Cumulative = 1 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Delta = 2 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.BaseExportingMetricReader -~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.Metrics.BaseExportingMetricReader.SupportedExportModes.get -> OpenTelemetry.Metrics.ExportModes OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration -~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.get -> double[] -~OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.set -> void OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.ExplicitBucketHistogramConfiguration() -> void OpenTelemetry.Metrics.ExportModes OpenTelemetry.Metrics.ExportModes.Pull = 2 -> OpenTelemetry.Metrics.ExportModes @@ -119,27 +209,18 @@ OpenTelemetry.Metrics.HistogramBuckets.Enumerator.Enumerator() -> void OpenTelemetry.Metrics.HistogramBuckets.Enumerator.MoveNext() -> bool OpenTelemetry.Metrics.HistogramBuckets.GetEnumerator() -> OpenTelemetry.Metrics.HistogramBuckets.Enumerator OpenTelemetry.Metrics.IPullMetricExporter -~OpenTelemetry.Metrics.IPullMetricExporter.Collect.get -> System.Func -~OpenTelemetry.Metrics.IPullMetricExporter.Collect.set -> void OpenTelemetry.Metrics.MeterProviderBuilderBase -~OpenTelemetry.Metrics.MeterProviderBuilderBase.Build() -> OpenTelemetry.Metrics.MeterProvider OpenTelemetry.Metrics.MeterProviderBuilderBase.MeterProviderBuilderBase() -> void OpenTelemetry.Metrics.MeterProviderBuilderExtensions OpenTelemetry.Metrics.MeterProviderExtensions OpenTelemetry.Metrics.Metric -~OpenTelemetry.Metrics.Metric.Description.get -> string OpenTelemetry.Metrics.Metric.GetMetricPoints() -> OpenTelemetry.Metrics.MetricPointsAccessor -~OpenTelemetry.Metrics.Metric.MeterName.get -> string -~OpenTelemetry.Metrics.Metric.MeterVersion.get -> string OpenTelemetry.Metrics.Metric.MetricType.get -> OpenTelemetry.Metrics.MetricType -~OpenTelemetry.Metrics.Metric.Name.get -> string OpenTelemetry.Metrics.Metric.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality -~OpenTelemetry.Metrics.Metric.Unit.get -> string OpenTelemetry.Metrics.MetricPoint OpenTelemetry.Metrics.MetricPoint.EndTime.get -> System.DateTimeOffset OpenTelemetry.Metrics.MetricPoint.GetGaugeLastValueDouble() -> double OpenTelemetry.Metrics.MetricPoint.GetGaugeLastValueLong() -> long -~OpenTelemetry.Metrics.MetricPoint.GetHistogramBuckets() -> OpenTelemetry.Metrics.HistogramBuckets OpenTelemetry.Metrics.MetricPoint.GetHistogramCount() -> long OpenTelemetry.Metrics.MetricPoint.GetHistogramSum() -> double OpenTelemetry.Metrics.MetricPoint.GetSumDouble() -> double @@ -163,21 +244,13 @@ OpenTelemetry.Metrics.MetricReader.TemporalityPreference.get -> OpenTelemetry.Me OpenTelemetry.Metrics.MetricReader.TemporalityPreference.set -> void OpenTelemetry.Metrics.MetricReaderOptions OpenTelemetry.Metrics.MetricReaderOptions.MetricReaderOptions() -> void -~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.get -> OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions -~OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.set -> void OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.get -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.set -> void OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Cumulative = 1 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Delta = 2 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference OpenTelemetry.Metrics.MetricStreamConfiguration -~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.get -> string -~OpenTelemetry.Metrics.MetricStreamConfiguration.Description.set -> void OpenTelemetry.Metrics.MetricStreamConfiguration.MetricStreamConfiguration() -> void -~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.get -> string -~OpenTelemetry.Metrics.MetricStreamConfiguration.Name.set -> void -~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] -~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void OpenTelemetry.Metrics.MetricType OpenTelemetry.Metrics.MetricType.DoubleGauge = 45 -> OpenTelemetry.Metrics.MetricType OpenTelemetry.Metrics.MetricType.DoubleSum = 29 -> OpenTelemetry.Metrics.MetricType @@ -186,7 +259,6 @@ OpenTelemetry.Metrics.MetricType.LongGauge = 42 -> OpenTelemetry.Metrics.MetricT OpenTelemetry.Metrics.MetricType.LongSum = 26 -> OpenTelemetry.Metrics.MetricType OpenTelemetry.Metrics.MetricTypeExtensions OpenTelemetry.Metrics.PeriodicExportingMetricReader -~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.get -> int? OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.set -> void @@ -197,27 +269,16 @@ OpenTelemetry.ProviderExtensions OpenTelemetry.ReadOnlyTagCollection OpenTelemetry.ReadOnlyTagCollection.Count.get -> int OpenTelemetry.ReadOnlyTagCollection.Enumerator -~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair OpenTelemetry.ReadOnlyTagCollection.Enumerator.Enumerator() -> void OpenTelemetry.ReadOnlyTagCollection.Enumerator.MoveNext() -> bool OpenTelemetry.ReadOnlyTagCollection.GetEnumerator() -> OpenTelemetry.ReadOnlyTagCollection.Enumerator OpenTelemetry.ReadOnlyTagCollection.ReadOnlyTagCollection() -> void OpenTelemetry.Resources.IResourceDetector -~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder OpenTelemetry.Resources.ResourceBuilderExtensions OpenTelemetry.Sdk OpenTelemetry.SimpleActivityExportProcessor -~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void -~OpenTelemetry.SimpleExportProcessor -~OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.SimpleLogRecordExportProcessor OpenTelemetry.SimpleLogRecordExportProcessor.SimpleLogRecordExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void OpenTelemetry.SuppressInstrumentationScope @@ -229,11 +290,7 @@ OpenTelemetry.Trace.AlwaysOnSampler.AlwaysOnSampler() -> void OpenTelemetry.Trace.BatchExportActivityProcessorOptions OpenTelemetry.Trace.BatchExportActivityProcessorOptions.BatchExportActivityProcessorOptions() -> void OpenTelemetry.Trace.ParentBasedSampler -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void OpenTelemetry.Trace.Sampler -~OpenTelemetry.Trace.Sampler.Description.get -> string -~OpenTelemetry.Trace.Sampler.Description.set -> void OpenTelemetry.Trace.Sampler.Sampler() -> void OpenTelemetry.Trace.SamplingDecision OpenTelemetry.Trace.SamplingDecision.Drop = 0 -> OpenTelemetry.Trace.SamplingDecision @@ -241,36 +298,25 @@ OpenTelemetry.Trace.SamplingDecision.RecordAndSample = 2 -> OpenTelemetry.Trace. OpenTelemetry.Trace.SamplingDecision.RecordOnly = 1 -> OpenTelemetry.Trace.SamplingDecision OpenTelemetry.Trace.SamplingParameters OpenTelemetry.Trace.SamplingParameters.Kind.get -> System.Diagnostics.ActivityKind -~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable -~OpenTelemetry.Trace.SamplingParameters.Name.get -> string OpenTelemetry.Trace.SamplingParameters.ParentContext.get -> System.Diagnostics.ActivityContext OpenTelemetry.Trace.SamplingParameters.SamplingParameters() -> void -~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void -~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.SamplingParameters.TraceId.get -> System.Diagnostics.ActivityTraceId OpenTelemetry.Trace.SamplingResult -~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.SamplingResult.Decision.get -> OpenTelemetry.Trace.SamplingDecision OpenTelemetry.Trace.SamplingResult.Equals(OpenTelemetry.Trace.SamplingResult other) -> bool OpenTelemetry.Trace.SamplingResult.SamplingResult() -> void OpenTelemetry.Trace.SamplingResult.SamplingResult(bool isSampled) -> void OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision) -> void -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void OpenTelemetry.Trace.TraceIdRatioBasedSampler OpenTelemetry.Trace.TraceIdRatioBasedSampler.TraceIdRatioBasedSampler(double probability) -> void OpenTelemetry.Trace.TracerProviderBuilderBase -~OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder -~OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider OpenTelemetry.Trace.TracerProviderBuilderBase.TracerProviderBuilderBase() -> void OpenTelemetry.Trace.TracerProviderBuilderExtensions OpenTelemetry.Trace.TracerProviderExtensions override OpenTelemetry.BaseExportProcessor.Dispose(bool disposing) -> void -~override OpenTelemetry.BaseExportProcessor.OnEnd(T data) -> void override OpenTelemetry.BaseExportProcessor.OnForceFlush(int timeoutMilliseconds) -> bool override OpenTelemetry.BaseExportProcessor.OnShutdown(int timeoutMilliseconds) -> bool -~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void override OpenTelemetry.BatchExportProcessor.Dispose(bool disposing) -> void -~override OpenTelemetry.BatchExportProcessor.OnExport(T data) -> void override OpenTelemetry.BatchExportProcessor.OnForceFlush(int timeoutMilliseconds) -> bool override OpenTelemetry.BatchExportProcessor.OnShutdown(int timeoutMilliseconds) -> bool override OpenTelemetry.BatchLogRecordExportProcessor.OnEnd(OpenTelemetry.Logs.LogRecord! data) -> void @@ -283,66 +329,23 @@ override OpenTelemetry.Logs.OpenTelemetryLoggerProvider.Dispose(bool disposing) override OpenTelemetry.Metrics.BaseExportingMetricReader.Dispose(bool disposing) -> void override OpenTelemetry.Metrics.BaseExportingMetricReader.OnCollect(int timeoutMilliseconds) -> bool override OpenTelemetry.Metrics.BaseExportingMetricReader.OnShutdown(int timeoutMilliseconds) -> bool -~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder -~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder override OpenTelemetry.Metrics.PeriodicExportingMetricReader.Dispose(bool disposing) -> void override OpenTelemetry.Metrics.PeriodicExportingMetricReader.OnShutdown(int timeoutMilliseconds) -> bool -~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void -~override OpenTelemetry.SimpleExportProcessor.OnExport(T data) -> void override OpenTelemetry.Trace.AlwaysOffSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult override OpenTelemetry.Trace.AlwaysOnSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult override OpenTelemetry.Trace.ParentBasedSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult -~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool override OpenTelemetry.Trace.SamplingResult.GetHashCode() -> int override OpenTelemetry.Trace.TraceIdRatioBasedSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult -~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder -~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder -~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder -~override sealed OpenTelemetry.BaseExportProcessor.OnStart(T data) -> void -~readonly OpenTelemetry.BaseExportProcessor.exporter -> OpenTelemetry.BaseExporter -~readonly OpenTelemetry.Metrics.BaseExportingMetricReader.exporter -> OpenTelemetry.BaseExporter static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder! -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Metrics.MetricReader reader) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, OpenTelemetry.Metrics.MetricStreamConfiguration metricStreamConfiguration) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, string name) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Func viewConfig) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProvider -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricPointsPerMetricStream(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricStreams(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricStreams) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Metrics.MeterProviderExtensions.ForceFlush(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool -~static OpenTelemetry.Metrics.MeterProviderExtensions.Shutdown(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool -~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration static OpenTelemetry.Metrics.MetricTypeExtensions.IsDouble(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsGauge(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsHistogram(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsLong(this OpenTelemetry.Metrics.MetricType self) -> bool static OpenTelemetry.Metrics.MetricTypeExtensions.IsSum(this OpenTelemetry.Metrics.MetricType self) -> bool -~static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider baseProvider) -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder -~static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator textMapPropagator) -> void static OpenTelemetry.Sdk.SuppressInstrumentation.get -> bool -~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable static OpenTelemetry.SuppressInstrumentationScope.Enter() -> int static OpenTelemetry.Trace.SamplingResult.operator !=(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool static OpenTelemetry.Trace.SamplingResult.operator ==(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.Trace.Sampler sampler) -> OpenTelemetry.Trace.TracerProviderBuilder -~static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor processor) -> OpenTelemetry.Trace.TracerProvider -~static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool -~static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool virtual OpenTelemetry.BaseExporter.Dispose(bool disposing) -> void virtual OpenTelemetry.BaseExporter.OnForceFlush(int timeoutMilliseconds) -> bool virtual OpenTelemetry.BaseExporter.OnShutdown(int timeoutMilliseconds) -> bool diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index ff0d049a675..e69de29bb2d 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,4 +0,0 @@ -#nullable enable -OpenTelemetry.Logs.LogRecord.FormattedMessage.set -> void -OpenTelemetry.Logs.LogRecord.State.set -> void -OpenTelemetry.Logs.LogRecord.StateValues.set -> void diff --git a/src/OpenTelemetry/AssemblyInfo.cs b/src/OpenTelemetry/AssemblyInfo.cs index 5b17a4357a6..545b35a13e8 100644 --- a/src/OpenTelemetry/AssemblyInfo.cs +++ b/src/OpenTelemetry/AssemblyInfo.cs @@ -17,6 +17,7 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("OpenTelemetry.Tests" + AssemblyInfo.PublicKey)] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.InMemory" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)] diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 43658db38d4..9e5ed04df1c 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -2,6 +2,23 @@ ## Unreleased +* `TracerProviderSDK` modified for spans with remote parent. For such spans + activity will be created irrespective of SamplingResult, to maintain context + propagation. + ([#3329](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3329)) + +* Fix issue where a measurement would be dropped when recording it with a + null-valued tag. + ([#3325](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3325)) + +## 1.3.0 + +Released 2022-Jun-03 + +## 1.3.0-rc.2 + +Released 2022-June-1 + * Fix null reference exception when a metric view does not match an instrument. ([#3285](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3285)) * Swallow `ObjectDisposedException` in `BatchExportProcessor` and diff --git a/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs b/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs index c80d41f28e5..0db72d4cba7 100644 --- a/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs +++ b/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs @@ -384,6 +384,12 @@ public void MetricViewIgnored(string instrumentName, string meterName, string re this.WriteEvent(41, instrumentName, meterName, reason, fix); } + [Event(42, Message = "Unsupported attribute type '{0}' for '{1}'. Attribute will not be exported.", Level = EventLevel.Warning)] + public void UnsupportedAttributeType(string type, string key) + { + this.WriteEvent(42, type.ToString(), key); + } + #if DEBUG public class OpenTelemetryEventListener : EventListener { diff --git a/src/OpenTelemetry/Internal/TagAndValueTransformer.cs b/src/OpenTelemetry/Internal/TagAndValueTransformer.cs new file mode 100644 index 00000000000..4438dfb9e31 --- /dev/null +++ b/src/OpenTelemetry/Internal/TagAndValueTransformer.cs @@ -0,0 +1,61 @@ +// +// 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. +// + +using System; +using System.Diagnostics; + +namespace OpenTelemetry.Internal; + +internal abstract class TagAndValueTransformer : TagTransformer +{ + protected TValue TransformValue(object value) + { + Debug.Assert(value != null, $"{nameof(value)} was null"); + + switch (value) + { + case char: + case string: + return this.TransformStringValue(Convert.ToString(value)); + case bool b: + return this.TransformBooleanValue(b); + case byte: + case sbyte: + case short: + case ushort: + case int: + case uint: + case long: + return this.TransformIntegralValue(Convert.ToInt64(value)); + case float: + case double: + return this.TransformFloatingPointValue(Convert.ToDouble(value)); + default: + // This could throw an exception. The caller is expected to handle. + return this.TransformStringValue(value.ToString()); + } + } + + protected abstract TValue TransformIntegralValue(long value); + + protected abstract TValue TransformFloatingPointValue(double value); + + protected abstract TValue TransformBooleanValue(bool value); + + protected abstract TValue TransformStringValue(string value); + + protected abstract TValue TransformArrayValue(Array value); +} diff --git a/src/OpenTelemetry/Internal/TagTransformer.cs b/src/OpenTelemetry/Internal/TagTransformer.cs new file mode 100644 index 00000000000..e63ccd623f9 --- /dev/null +++ b/src/OpenTelemetry/Internal/TagTransformer.cs @@ -0,0 +1,138 @@ +// +// 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. +// + +using System; +using System.Collections.Generic; + +namespace OpenTelemetry.Internal; + +internal abstract class TagTransformer +{ + public bool TryTransformTag(KeyValuePair tag, out T result) + { + if (tag.Value == null) + { + result = default; + return false; + } + + switch (tag.Value) + { + case char: + case string: + result = this.TransformStringTag(tag.Key, Convert.ToString(tag.Value)); + break; + case bool b: + result = this.TransformBooleanTag(tag.Key, b); + break; + case byte: + case sbyte: + case short: + case ushort: + case int: + case uint: + case long: + result = this.TransformIntegralTag(tag.Key, Convert.ToInt64(tag.Value)); + break; + case float: + case double: + result = this.TransformFloatingPointTag(tag.Key, Convert.ToDouble(tag.Value)); + break; + case Array array: + try + { + result = this.TransformArrayTagInternal(tag.Key, array); + } + catch + { + // If an exception is thrown when calling ToString + // on any element of the array, then the entire array value + // is ignored. + OpenTelemetrySdkEventSource.Log.UnsupportedAttributeType(tag.Value.GetType().ToString(), tag.Key); + result = default; + return false; + } + + break; + + // All other types are converted to strings including the following + // built-in value types: + // case nint: Pointer type. + // case nuint: Pointer type. + // case ulong: May throw an exception on overflow. + // case decimal: Converting to double produces rounding errors. + default: + try + { + result = this.TransformStringTag(tag.Key, tag.Value.ToString()); + } + catch + { + // If ToString throws an exception then the tag is ignored. + OpenTelemetrySdkEventSource.Log.UnsupportedAttributeType(tag.Value.GetType().ToString(), tag.Key); + result = default; + return false; + } + + break; + } + + return true; + } + + protected abstract T TransformIntegralTag(string key, long value); + + protected abstract T TransformFloatingPointTag(string key, double value); + + protected abstract T TransformBooleanTag(string key, bool value); + + protected abstract T TransformStringTag(string key, string value); + + protected abstract T TransformArrayTag(string key, Array array); + + private T TransformArrayTagInternal(string key, Array array) + { + // This switch ensures the values of the resultant array-valued tag are of the same type. + return array switch + { + char[] => this.TransformArrayTag(key, array), + string[] => this.TransformArrayTag(key, array), + bool[] => this.TransformArrayTag(key, array), + byte[] => this.TransformArrayTag(key, array), + sbyte[] => this.TransformArrayTag(key, array), + short[] => this.TransformArrayTag(key, array), + ushort[] => this.TransformArrayTag(key, array), + int[] => this.TransformArrayTag(key, array), + uint[] => this.TransformArrayTag(key, array), + long[] => this.TransformArrayTag(key, array), + float[] => this.TransformArrayTag(key, array), + double[] => this.TransformArrayTag(key, array), + _ => this.ConvertToStringArrayThenTransformArrayTag(key, array), + }; + } + + private T ConvertToStringArrayThenTransformArrayTag(string key, Array array) + { + var stringArray = new string[array.Length]; + + for (var i = 0; i < array.Length; ++i) + { + stringArray[i] = array.GetValue(i)?.ToString(); + } + + return this.TransformArrayTag(key, stringArray); + } +} diff --git a/src/OpenTelemetry/Metrics/Tags.cs b/src/OpenTelemetry/Metrics/Tags.cs index 6f3b4ba62dd..e7996bd846a 100644 --- a/src/OpenTelemetry/Metrics/Tags.cs +++ b/src/OpenTelemetry/Metrics/Tags.cs @@ -20,10 +20,23 @@ namespace OpenTelemetry.Metrics { internal readonly struct Tags : IEquatable { + private readonly int hashCode; + public Tags(string[] keys, object[] values) { this.Keys = keys; this.Values = values; + + unchecked + { + var hash = 17; + for (int i = 0; i < this.Keys.Length; i++) + { + hash = (hash * 31) + this.Keys[i].GetHashCode() + this.Values[i]?.GetHashCode() ?? 0; + } + + this.hashCode = hash; + } } public readonly string[] Keys { get; } @@ -78,19 +91,6 @@ public readonly bool Equals(Tags other) return true; } - public override readonly int GetHashCode() - { - int hash = 17; - - unchecked - { - for (int i = 0; i < this.Keys.Length; i++) - { - hash = (hash * 31) + this.Keys[i].GetHashCode() + this.Values[i].GetHashCode(); - } - } - - return hash; - } + public override readonly int GetHashCode() => this.hashCode; } } diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index a247eba4f37..a1f2cf59445 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -10,12 +10,6 @@ core- - - - false - - diff --git a/src/OpenTelemetry/Trace/TracerProviderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderSdk.cs index 4f2a292e6e3..cd760e29548 100644 --- a/src/OpenTelemetry/Trace/TracerProviderSdk.cs +++ b/src/OpenTelemetry/Trace/TracerProviderSdk.cs @@ -199,7 +199,7 @@ internal TracerProviderSdk( else if (sampler is AlwaysOffSampler) { listener.Sample = (ref ActivityCreationOptions options) => - !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.TraceId) : ActivitySamplingResult.None; + !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent) : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataAlwaysOffSampler; } else @@ -393,17 +393,17 @@ private static ActivitySamplingResult ComputeActivitySamplingResult( return activitySamplingResult; } - return PropagateOrIgnoreData(options.Parent.TraceId); + return PropagateOrIgnoreData(options.Parent); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ActivitySamplingResult PropagateOrIgnoreData(ActivityTraceId traceId) + private static ActivitySamplingResult PropagateOrIgnoreData(in ActivityContext parentContext) { - var isRootSpan = traceId == default; + var isRootSpan = parentContext.TraceId == default; - // If it is the root span select PropagationData so the trace ID is preserved + // If it is the root span or the parent is remote select PropagationData so the trace ID is preserved // even if no activity of the trace is recorded (sampled per OpenTelemetry parlance). - return isRootSpan + return (isRootSpan || parentContext.IsRemote) ? ActivitySamplingResult.PropagationData : ActivitySamplingResult.None; } diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerActivityConversionTest.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerActivityConversionTest.cs index 44567a04294..ad4d6db9c01 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerActivityConversionTest.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerActivityConversionTest.cs @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // + using System; using System.Collections.Generic; using System.Diagnostics; @@ -102,18 +103,15 @@ public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_AllPropertie var logs = jaegerSpan.Logs.ToArray(); var jaegerLog = logs[0]; Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); - Assert.Equal(4, jaegerLog.Fields.Count); + Assert.Equal(3, jaegerLog.Fields.Count); var eventFields = jaegerLog.Fields.ToArray(); var eventField = eventFields[0]; Assert.Equal("key", eventField.Key); Assert.Equal("value", eventField.VStr); eventField = eventFields[1]; Assert.Equal("string_array", eventField.Key); - Assert.Equal("a", eventField.VStr); + Assert.Equal(@"[""a"",""b""]", eventField.VStr); eventField = eventFields[2]; - Assert.Equal("string_array", eventField.Key); - Assert.Equal("b", eventField.VStr); - eventField = eventFields[3]; Assert.Equal("event", eventField.Key); Assert.Equal("Event1", eventField.VStr); @@ -167,12 +165,12 @@ public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_NoAttributes var logs = jaegerSpan.Logs.ToArray(); var jaegerLog = logs[0]; Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); - Assert.Equal(4, jaegerLog.Fields.Count); + Assert.Equal(3, jaegerLog.Fields.Count); var eventFields = jaegerLog.Fields.ToArray(); var eventField = eventFields[0]; Assert.Equal("key", eventField.Key); Assert.Equal("value", eventField.VStr); - eventField = eventFields[3]; + eventField = eventFields[2]; Assert.Equal("event", eventField.Key); Assert.Equal("Event1", eventField.VStr); @@ -298,24 +296,29 @@ public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_NoLinks() Assert.Equal(true, tag.VBool); tag = tags[6]; - Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal(JaegerTagType.STRING, tag.VType); Assert.Equal("int_array", tag.Key); - Assert.Equal(1, tag.VLong); + Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { 1, 2 }), tag.VStr); - tag = tags[8]; - Assert.Equal(JaegerTagType.BOOL, tag.VType); + tag = tags[7]; + Assert.Equal(JaegerTagType.STRING, tag.VType); Assert.Equal("bool_array", tag.Key); - Assert.Equal(true, tag.VBool); + Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { true, false }), tag.VStr); - tag = tags[10]; - Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + tag = tags[8]; + Assert.Equal(JaegerTagType.STRING, tag.VType); Assert.Equal("double_array", tag.Key); - Assert.Equal(1, tag.VDouble); + Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { 1, 1.1 }), tag.VStr); - tag = tags[12]; + tag = tags[9]; Assert.Equal(JaegerTagType.STRING, tag.VType); Assert.Equal("string_array", tag.Key); - Assert.Equal("a", tag.VStr); + Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { "a", "b" }), tag.VStr); + + tag = tags[10]; + Assert.Equal(JaegerTagType.STRING, tag.VType); + Assert.Equal("obj_array", tag.Key); + Assert.Equal(System.Text.Json.JsonSerializer.Serialize(new[] { 1.ToString(), false.ToString(), new object().ToString(), "string", string.Empty, null }), tag.VStr); // The second to last tag should be span.kind in this case tag = tags[tags.Length - 2]; @@ -332,12 +335,12 @@ public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_NoLinks() var logs = jaegerSpan.Logs.ToArray(); var jaegerLog = logs[0]; Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); - Assert.Equal(4, jaegerLog.Fields.Count); + Assert.Equal(3, jaegerLog.Fields.Count); var eventFields = jaegerLog.Fields.ToArray(); var eventField = eventFields[0]; Assert.Equal("key", eventField.Key); Assert.Equal("value", eventField.VStr); - eventField = eventFields[3]; + eventField = eventFields[2]; Assert.Equal("event", eventField.Key); Assert.Equal("Event1", eventField.VStr); Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); @@ -635,6 +638,8 @@ internal static Activity CreateTestActivity( var attributes = new Dictionary { + { "exceptionFromToString", new MyToStringMethodThrowsAnException() }, + { "exceptionFromToStringInArray", new MyToStringMethodThrowsAnException[] { new MyToStringMethodThrowsAnException() } }, { "stringKey", "value" }, { "longKey", 1L }, { "longKey2", 1 }, @@ -645,6 +650,7 @@ internal static Activity CreateTestActivity( { "bool_array", new bool[] { true, false } }, { "double_array", new double[] { 1.0, 1.1 } }, { "string_array", new string[] { "a", "b" } }, + { "obj_array", new object[] { 1, false, new object(), "string", string.Empty, null } }, }; if (additionalAttributes != null) { @@ -847,5 +853,13 @@ public override string ToString() return this.Name; } } + + private class MyToStringMethodThrowsAnException + { + public override string ToString() + { + throw new Exception("Nope."); + } + } } } diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsExtensionsTests.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterProtocolParserTests.cs similarity index 54% rename from test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsExtensionsTests.cs rename to test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterProtocolParserTests.cs index 0dfca9cc3cd..c75a52d674a 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsExtensionsTests.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterProtocolParserTests.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,16 +18,17 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests; -public class JaegerExporterOptionsExtensionsTests +public class JaegerExporterProtocolParserTests { [Theory] - [InlineData("udp/thrift.compact", JaegerExportProtocol.UdpCompactThrift)] - [InlineData("http/thrift.binary", JaegerExportProtocol.HttpBinaryThrift)] - [InlineData("unsupported", null)] - public void ToJaegerExportProtocol_Protocol_MapsToCorrectValue(string protocol, JaegerExportProtocol? expectedExportProtocol) + [InlineData("udp/thrift.compact", true, JaegerExportProtocol.UdpCompactThrift)] + [InlineData("http/thrift.binary", true, JaegerExportProtocol.HttpBinaryThrift)] + [InlineData("unsupported", false, default(JaegerExportProtocol))] + public void TryParse_Protocol_MapsToCorrectValue(string protocol, bool expectedResult, JaegerExportProtocol expectedExportProtocol) { - var exportProtocol = protocol.ToJaegerExportProtocol(); + var result = JaegerExporterProtocolParser.TryParse(protocol, out var exportProtocol); Assert.Equal(expectedExportProtocol, exportProtocol); + Assert.Equal(expectedResult, result); } } diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs index 82096ba587c..5d018bcf8c1 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs @@ -201,7 +201,8 @@ public void JaegerTraceExporter_SetResource_CombinesTags() using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions()); var process = jaegerTraceExporter.Process; - process.Tags = new Dictionary { ["Tag1"] = new KeyValuePair("Tag1", "value1").ToJaegerTag() }; + JaegerTagTransformer.Instance.TryTransformTag(new KeyValuePair("Tag1", "value1"), out var result); + process.Tags = new Dictionary { ["Tag1"] = result }; jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddAttributes(new Dictionary { diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs index 60652ec0957..8b97444dee1 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs @@ -29,22 +29,19 @@ public class OtlpAttributeTests public void NullValueAttribute() { var kvp = new KeyValuePair("key", null); - var attribute = kvp.ToOtlpAttribute(); - Assert.Null(attribute); + Assert.False(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var _)); } [Fact] public void EmptyArrays() { - var kvp = new KeyValuePair("key", new int[] { }); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + var kvp = new KeyValuePair("key", Array.Empty()); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase); Assert.Empty(attribute.Value.ArrayValue.Values); - kvp = new KeyValuePair("key", new object[] { }); - attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + kvp = new KeyValuePair("key", Array.Empty()); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase); Assert.Empty(attribute.Value.ArrayValue.Values); } @@ -67,8 +64,7 @@ public void EmptyArrays() public void IntegralTypesSupported(object value) { var kvp = new KeyValuePair("key", value); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); switch (value) { @@ -97,8 +93,7 @@ public void IntegralTypesSupported(object value) public void FloatingPointTypesSupported(object value) { var kvp = new KeyValuePair("key", value); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); switch (value) { @@ -125,8 +120,7 @@ public void FloatingPointTypesSupported(object value) public void BooleanTypeSupported(object value) { var kvp = new KeyValuePair("key", value); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); switch (value) { @@ -153,8 +147,7 @@ public void BooleanTypeSupported(object value) public void StringTypesSupported(object value) { var kvp = new KeyValuePair("key", value); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.StringValue, attribute.Value.ValueCase); Assert.Equal(Convert.ToString(value), attribute.Value.StringValue); } @@ -166,14 +159,12 @@ public void StringArrayTypesSupported() var stringArray = new string[] { "a", "b", "c", string.Empty, null }; var kvp = new KeyValuePair("key", charArray); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase); Assert.Equal(charArray.Select(x => x.ToString()), attribute.Value.ArrayValue.Values.Select(x => x.StringValue)); kvp = new KeyValuePair("key", stringArray); - attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase); for (var i = 0; i < stringArray.Length; ++i) @@ -213,8 +204,7 @@ public void ToStringIsCalledForAllOtherTypes() foreach (var value in testValues) { var kvp = new KeyValuePair("key", value); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.StringValue, attribute.Value.ValueCase); Assert.Equal(value.ToString(), attribute.Value.StringValue); } @@ -222,8 +212,7 @@ public void ToStringIsCalledForAllOtherTypes() foreach (var value in testArrayValues) { var kvp = new KeyValuePair("key", value); - var attribute = kvp.ToOtlpAttribute(); - Assert.NotNull(attribute); + Assert.True(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var attribute)); Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase); var array = value as Array; @@ -247,12 +236,10 @@ public void ToStringIsCalledForAllOtherTypes() public void ExceptionInToStringIsCaught() { var kvp = new KeyValuePair("key", new MyToStringMethodThrowsAnException()); - var attribute = kvp.ToOtlpAttribute(); - Assert.Null(attribute); + Assert.False(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var _)); kvp = new KeyValuePair("key", new object[] { 1, false, new MyToStringMethodThrowsAnException() }); - attribute = kvp.ToOtlpAttribute(); - Assert.Null(attribute); + Assert.False(OtlpKeyValueTransformer.Instance.TryTransformTag(kvp, out var _)); } private class MyToStringMethodThrowsAnException diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExportProtocolParserTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExportProtocolParserTests.cs new file mode 100644 index 00000000000..baec4253e73 --- /dev/null +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExportProtocolParserTests.cs @@ -0,0 +1,35 @@ +// +// 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. +// + +using Xunit; + +namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests +{ + public class OtlpExportProtocolParserTests : Http2UnencryptedSupportTests + { + [Theory] + [InlineData("grpc", true, OtlpExportProtocol.Grpc)] + [InlineData("http/protobuf", true, OtlpExportProtocol.HttpProtobuf)] + [InlineData("unsupported", false, default(OtlpExportProtocol))] + public void TryParse_Protocol_MapsToCorrectValue(string protocol, bool expectedResult, OtlpExportProtocol expectedExportProtocol) + { + var result = OtlpExportProtocolParser.TryParse(protocol, out var exportProtocol); + + Assert.Equal(expectedExportProtocol, exportProtocol); + Assert.Equal(expectedResult, result); + } + } +} diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsExtensionsTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsExtensionsTests.cs index 27864f9c74f..4b4dd25fd53 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsExtensionsTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsExtensionsTests.cs @@ -145,17 +145,6 @@ public void GetTraceExportClient_UnsupportedProtocol_Throws() Assert.Throws(() => options.GetTraceExportClient()); } - [Theory] - [InlineData("grpc", OtlpExportProtocol.Grpc)] - [InlineData("http/protobuf", OtlpExportProtocol.HttpProtobuf)] - [InlineData("unsupported", null)] - public void ToOtlpExportProtocol_Protocol_MapsToCorrectValue(string protocol, OtlpExportProtocol? expectedExportProtocol) - { - var exportProtocol = protocol.ToOtlpExportProtocol(); - - Assert.Equal(expectedExportProtocol, exportProtocol); - } - [Theory] [InlineData("http://test:8888", "http://test:8888/v1/traces")] [InlineData("http://test:8888/", "http://test:8888/v1/traces")] diff --git a/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs b/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs index 2e34b9d465e..37b715501a6 100644 --- a/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs +++ b/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs @@ -359,7 +359,7 @@ public void IntegrationTest( } Assert.Equal( - $@"[{{""traceId"":""{traceId}"",""name"":""Name"",{parentId}""id"":""{ZipkinActivityConversionExtensions.EncodeSpanId(context.SpanId)}"",""kind"":""CLIENT"",""timestamp"":{timestamp},""duration"":60000000,""localEndpoint"":{{""serviceName"":""{serviceName}""{ipInformation}}},""remoteEndpoint"":{{""serviceName"":""http://localhost:44312/""}},""annotations"":[{{""timestamp"":{eventTimestamp},""value"":""Event1""}},{{""timestamp"":{eventTimestamp},""value"":""Event2""}}],""tags"":{{{resourceTags}""stringKey"":""value"",""longKey"":""1"",""longKey2"":""1"",""doubleKey"":""1"",""doubleKey2"":""1"",""longArrayKey"":""1,2"",""boolKey"":""true"",""boolArrayKey"":""true,false"",""http.host"":""http://localhost:44312/"",{statusTag}{errorTag}""otel.library.name"":""CreateTestActivity"",""peer.service"":""http://localhost:44312/""}}}}]", + $@"[{{""traceId"":""{traceId}"",""name"":""Name"",{parentId}""id"":""{ZipkinActivityConversionExtensions.EncodeSpanId(context.SpanId)}"",""kind"":""CLIENT"",""timestamp"":{timestamp},""duration"":60000000,""localEndpoint"":{{""serviceName"":""{serviceName}""{ipInformation}}},""remoteEndpoint"":{{""serviceName"":""http://localhost:44312/""}},""annotations"":[{{""timestamp"":{eventTimestamp},""value"":""Event1""}},{{""timestamp"":{eventTimestamp},""value"":""Event2""}}],""tags"":{{{resourceTags}""stringKey"":""value"",""longKey"":""1"",""longKey2"":""1"",""doubleKey"":""1"",""doubleKey2"":""1"",""longArrayKey"":""[1,2]"",""boolKey"":""true"",""boolArrayKey"":""[true,false]"",""http.host"":""http://localhost:44312/"",{statusTag}{errorTag}""otel.library.name"":""CreateTestActivity"",""peer.service"":""http://localhost:44312/""}}}}]", Responses[requestId]); } diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptionsExtensions.cs b/test/OpenTelemetry.Extensions.Propagators.Tests/EventSourceTest.cs similarity index 56% rename from src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptionsExtensions.cs rename to test/OpenTelemetry.Extensions.Propagators.Tests/EventSourceTest.cs index 12f225e421d..fdc75a02c75 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptionsExtensions.cs +++ b/test/OpenTelemetry.Extensions.Propagators.Tests/EventSourceTest.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,15 +14,18 @@ // limitations under the License. // -namespace OpenTelemetry.Exporter; +using OpenTelemetry.Internal; +using OpenTelemetry.Tests; +using Xunit; -internal static class JaegerExporterOptionsExtensions +namespace OpenTelemetry.Instrumentation.SqlClient.Tests { - public static JaegerExportProtocol? ToJaegerExportProtocol(this string protocol) => - protocol?.Trim() switch + public class EventSourceTest + { + [Fact] + public void EventSourceTest_PropagatorsEventSource() { - "udp/thrift.compact" => JaegerExportProtocol.UdpCompactThrift, - "http/thrift.binary" => JaegerExportProtocol.HttpBinaryThrift, - _ => null, - }; + EventSourceTestHelper.MethodsAreImplementedConsistentlyWithTheirAttributes(OpenTelemetryPropagatorsEventSource.Log); + } + } } diff --git a/test/OpenTelemetry.Extensions.Propagators.Tests/OpenTelemetry.Extensions.Propagators.Tests.csproj b/test/OpenTelemetry.Extensions.Propagators.Tests/OpenTelemetry.Extensions.Propagators.Tests.csproj index a31f662fbd7..9186da7a943 100644 --- a/test/OpenTelemetry.Extensions.Propagators.Tests/OpenTelemetry.Extensions.Propagators.Tests.csproj +++ b/test/OpenTelemetry.Extensions.Propagators.Tests/OpenTelemetry.Extensions.Propagators.Tests.csproj @@ -6,6 +6,11 @@ $(TARGET_FRAMEWORK) + + + + + diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs index b3785d63cf1..03dc2b9d6e3 100644 --- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs @@ -64,12 +64,12 @@ public void AddAspNetCoreInstrumentation_BadArgs() [Fact] public async Task StatusIsUnsetOn200Response() { - var activityProcessor = new Mock>(); + var exportedItems = new List(); void ConfigureTestServices(IServiceCollection services) { this.tracerProvider = Sdk.CreateTracerProviderBuilder() .AddAspNetCoreInstrumentation() - .AddProcessor(activityProcessor.Object) + .AddInMemoryExporter(exportedItems) .Build(); } @@ -85,14 +85,11 @@ void ConfigureTestServices(IServiceCollection services) // Assert response.EnsureSuccessStatusCode(); // Status Code 200-299 - WaitForProcessorInvocations(activityProcessor, 3); + WaitForActivityExport(exportedItems, 1); } - Assert.Equal(3, activityProcessor.Invocations.Count); // begin and end was called - - // we should only call Processor.OnEnd for the "/api/values" request - Assert.Single(activityProcessor.Invocations, invo => invo.Method.Name == "OnEnd"); - var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity; + Assert.Single(exportedItems); + var activity = exportedItems[0]; Assert.Equal(200, activity.GetTagValue(SemanticConventions.AttributeHttpStatusCode)); @@ -107,8 +104,7 @@ void ConfigureTestServices(IServiceCollection services) [InlineData(false)] public async Task SuccessfulTemplateControllerCallGeneratesASpan(bool shouldEnrich) { - var activityProcessor = new Mock>(); - activityProcessor.Setup(x => x.OnStart(It.IsAny())).Callback(c => c.SetTag("enriched", "no")); + var exportedItems = new List(); void ConfigureTestServices(IServiceCollection services) { this.tracerProvider = Sdk.CreateTracerProviderBuilder() @@ -119,7 +115,7 @@ void ConfigureTestServices(IServiceCollection services) options.Enrich = ActivityEnrichment; } }) - .AddProcessor(activityProcessor.Object) + .AddInMemoryExporter(exportedItems) .Build(); } @@ -135,14 +131,16 @@ void ConfigureTestServices(IServiceCollection services) // Assert response.EnsureSuccessStatusCode(); // Status Code 200-299 - WaitForProcessorInvocations(activityProcessor, 3); + WaitForActivityExport(exportedItems, 1); } - Assert.Equal(3, activityProcessor.Invocations.Count); // begin and end was called - var activity = (Activity)activityProcessor.Invocations[2].Arguments[0]; + Assert.Single(exportedItems); + var activity = exportedItems[0]; - Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enriched")); - Assert.Equal(shouldEnrich ? "yes" : "no", activity.Tags.Where(tag => tag.Key == "enriched").FirstOrDefault().Value); + if (shouldEnrich) + { + Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enriched" && tag.Value == "yes")); + } ValidateAspNetCoreActivity(activity, "/api/values"); } @@ -150,8 +148,7 @@ void ConfigureTestServices(IServiceCollection services) [Fact] public async Task SuccessfulTemplateControllerCallUsesParentContext() { - var activityProcessor = new Mock>(); - + var exportedItems = new List(); var expectedTraceId = ActivityTraceId.CreateRandom(); var expectedSpanId = ActivitySpanId.CreateRandom(); @@ -161,7 +158,7 @@ public async Task SuccessfulTemplateControllerCallUsesParentContext() builder.ConfigureTestServices(services => { this.tracerProvider = Sdk.CreateTracerProviderBuilder().AddAspNetCoreInstrumentation() - .AddProcessor(activityProcessor.Object) + .AddInMemoryExporter(exportedItems) .Build(); }))) { @@ -175,18 +172,11 @@ public async Task SuccessfulTemplateControllerCallUsesParentContext() // Assert response.EnsureSuccessStatusCode(); // Status Code 200-299 - WaitForProcessorInvocations(activityProcessor, 3); + WaitForActivityExport(exportedItems, 1); } - // List of invocations - // 1. SetParentProvider for TracerProviderSdk - // 2. OnStart for the activity created by AspNetCore with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - // 3. OnStart for the sibling activity created by the instrumentation library with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn and the first tag that is added is (IsCreatedByInstrumentation, bool.TrueString) - // 4. OnEnd for the sibling activity created by the instrumentation library with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn and the first tag that is added is (IsCreatedByInstrumentation, bool.TrueString) - - // we should only call Processor.OnEnd once for the sibling activity - Assert.Single(activityProcessor.Invocations, invo => invo.Method.Name == "OnEnd"); - var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity; + Assert.Single(exportedItems); + var activity = exportedItems[0]; Assert.Equal("Microsoft.AspNetCore.Hosting.HttpRequestIn", activity.OperationName); Assert.Equal("api/Values/{id}", activity.DisplayName); @@ -202,8 +192,7 @@ public async Task CustomPropagator() { try { - var activityProcessor = new Mock>(); - + var exportedItems = new List(); var expectedTraceId = ActivityTraceId.CreateRandom(); var expectedSpanId = ActivitySpanId.CreateRandom(); @@ -224,7 +213,7 @@ public async Task CustomPropagator() Sdk.SetDefaultTextMapPropagator(propagator.Object); this.tracerProvider = Sdk.CreateTracerProviderBuilder() .AddAspNetCoreInstrumentation() - .AddProcessor(activityProcessor.Object) + .AddInMemoryExporter(exportedItems) .Build(); }))) { @@ -232,32 +221,12 @@ public async Task CustomPropagator() var response = await client.GetAsync("/api/values/2"); response.EnsureSuccessStatusCode(); // Status Code 200-299 - WaitForProcessorInvocations(activityProcessor, 4); + WaitForActivityExport(exportedItems, 1); } - // List of invocations on the processor - // 1. SetParentProvider for TracerProviderSdk - // 2. OnStart for the activity created by AspNetCore with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - // 3. OnStart for the sibling activity created by the instrumentation library with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn and the first tag that is added is (IsCreatedByInstrumentation, bool.TrueString) - // 4. OnEnd for the sibling activity created by the instrumentation library with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn and the first tag that is added is (IsCreatedByInstrumentation, bool.TrueString) - Assert.Equal(4, activityProcessor.Invocations.Count); - - var startedActivities = activityProcessor.Invocations.Where(invo => invo.Method.Name == "OnStart"); - var stoppedActivities = activityProcessor.Invocations.Where(invo => invo.Method.Name == "OnEnd"); - Assert.Equal(2, startedActivities.Count()); - Assert.Single(stoppedActivities); + Assert.Single(exportedItems); + var activity = exportedItems[0]; - // The activity created by the framework and the sibling activity are both sent to Processor.OnStart - Assert.Equal(2, startedActivities.Count(item => - { - var startedActivity = item.Arguments[0] as Activity; - return startedActivity.OperationName == HttpInListener.ActivityOperationName; - })); - - // we should only call Processor.OnEnd once for the sibling activity - Assert.Single(activityProcessor.Invocations, invo => invo.Method.Name == "OnEnd"); - - var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity; Assert.True(activity.Duration != TimeSpan.Zero); Assert.Equal("api/Values/{id}", activity.DisplayName); @@ -279,13 +248,13 @@ public async Task CustomPropagator() [Fact] public async Task RequestNotCollectedWhenFilterIsApplied() { - var activityProcessor = new Mock>(); + var exportedItems = new List(); void ConfigureTestServices(IServiceCollection services) { this.tracerProvider = Sdk.CreateTracerProviderBuilder() .AddAspNetCoreInstrumentation((opt) => opt.Filter = (ctx) => ctx.Request.Path != "/api/values/2") - .AddProcessor(activityProcessor.Object) + .AddInMemoryExporter(exportedItems) .Build(); } @@ -304,18 +273,11 @@ void ConfigureTestServices(IServiceCollection services) response1.EnsureSuccessStatusCode(); // Status Code 200-299 response2.EnsureSuccessStatusCode(); // Status Code 200-299 - WaitForProcessorInvocations(activityProcessor, 4); + WaitForActivityExport(exportedItems, 1); } - // 1. SetParentProvider for TracerProviderSdk - // 2. OnStart for the activity created by AspNetCore for "/api/values" with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - // 3. OnEnd for the activity created by AspNetCore for "/api/values" with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - // 4. OnStart for the activity created by AspNetCore for "/api/values/2" with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - Assert.Equal(4, activityProcessor.Invocations.Count); - - // we should only call Processor.OnEnd for the "/api/values" request - Assert.Single(activityProcessor.Invocations, invo => invo.Method.Name == "OnEnd"); - var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity; + Assert.Single(exportedItems); + var activity = exportedItems[0]; ValidateAspNetCoreActivity(activity, "/api/values"); } @@ -323,7 +285,7 @@ void ConfigureTestServices(IServiceCollection services) [Fact] public async Task RequestNotCollectedWhenFilterThrowException() { - var activityProcessor = new Mock>(); + var exportedItems = new List(); void ConfigureTestServices(IServiceCollection services) { @@ -339,7 +301,7 @@ void ConfigureTestServices(IServiceCollection services) return true; } }) - .AddProcessor(activityProcessor.Object) + .AddInMemoryExporter(exportedItems) .Build(); } @@ -361,22 +323,14 @@ void ConfigureTestServices(IServiceCollection services) Assert.Single(inMemoryEventListener.Events.Where((e) => e.EventId == 3)); } - WaitForProcessorInvocations(activityProcessor, 3); + WaitForActivityExport(exportedItems, 1); } // As InstrumentationFilter threw, we continue as if the // InstrumentationFilter did not exist. - // List of invocations on the processor - // 1. SetParentProvider for TracerProviderSdk - // 2. OnStart for the activity created by AspNetCore for "/api/values" with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - // 3. OnEnd for the activity created by AspNetCore for "/api/values" with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - // 4. OnStart for the activity created by AspNetCore for "/api/values/2" with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn - - // we should only call Processor.OnEnd for the "/api/values" request - Assert.Single(activityProcessor.Invocations, invo => invo.Method.Name == "OnEnd"); - var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity; - + Assert.Single(exportedItems); + var activity = exportedItems[0]; ValidateAspNetCoreActivity(activity, "/api/values"); } @@ -601,7 +555,7 @@ public void Dispose() this.tracerProvider?.Dispose(); } - private static void WaitForProcessorInvocations(Mock> activityProcessor, int invocationCount) + private static void WaitForActivityExport(List exportedItems, int count) { // We need to let End callback execute as it is executed AFTER response was returned. // In unit tests environment there may be a lot of parallel unit tests executed, so @@ -610,7 +564,7 @@ private static void WaitForProcessorInvocations(Mock> ac () => { Thread.Sleep(10); - return activityProcessor.Invocations.Count >= invocationCount; + return exportedItems.Count >= count; }, TimeSpan.FromSeconds(1))); } diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index 08d6feeea26..84927ed7e2e 100644 --- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -15,6 +15,7 @@ // using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -23,7 +24,6 @@ using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; -using Moq; using OpenTelemetry.Trace; #if NETCOREAPP3_1 using TestApp.AspNetCore._3._1; @@ -58,7 +58,7 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan( string reasonPhrase, bool recordException = false) { - var processor = new Mock>(); + var exportedItems = new List(); // Arrange using (var client = this.factory @@ -67,7 +67,7 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan( { services.AddSingleton(new TestCallbackMiddlewareImpl(statusCode, reasonPhrase)); services.AddOpenTelemetryTracing((builder) => builder.AddAspNetCoreInstrumentation(options => options.RecordException = recordException) - .AddProcessor(processor.Object)); + .AddInMemoryExporter(exportedItems)); })) .CreateClient()) { @@ -94,7 +94,7 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan( for (var i = 0; i < 10; i++) { - if (processor.Invocations.Count == 3) + if (exportedItems.Count == 1) { break; } @@ -106,8 +106,8 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan( } } - Assert.Equal(3, processor.Invocations.Count); // SetParentProvider/Begin/End called - var activity = (Activity)processor.Invocations[2].Arguments[0]; + Assert.Single(exportedItems); + var activity = exportedItems[0]; Assert.Equal(ActivityKind.Server, activity.Kind); Assert.Equal("localhost", activity.GetTagValue(SemanticConventions.AttributeHttpHost)); @@ -145,7 +145,6 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan( ValidateTagValue(activity, SemanticConventions.AttributeHttpUserAgent, userAgent); activity.Dispose(); - processor.Object.Dispose(); } private static void ValidateTagValue(Activity activity, string attribute, string expectedValue) diff --git a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Dockerfile b/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Dockerfile deleted file mode 100644 index 5f3f9f866c2..00000000000 --- a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -# Create a container for running the OpenTelemetry Redis integration tests. -# This should be run from the root of the repo: -# docker build --file test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Dockerfile . - -ARG SDK_VERSION=6.0 -FROM mcr.microsoft.com/dotnet/sdk:6.0-focal AS build -ARG PUBLISH_CONFIGURATION=Release -ARG PUBLISH_FRAMEWORK=net6.0 -WORKDIR /repo -COPY . ./ -WORKDIR "/repo/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests" -RUN dotnet publish "OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.csproj" -c "${PUBLISH_CONFIGURATION}" -f "${PUBLISH_FRAMEWORK}" -o /drop -p:IntegrationBuild=true -p:TARGET_FRAMEWORK=${PUBLISH_FRAMEWORK} - -FROM mcr.microsoft.com/dotnet/sdk:${SDK_VERSION} AS final -WORKDIR /test -COPY --from=build /drop . -ENTRYPOINT ["dotnet", "vstest", "OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.dll"] diff --git a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToActivityConverterTests.cs b/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToActivityConverterTests.cs deleted file mode 100644 index 578e3f613c8..00000000000 --- a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToActivityConverterTests.cs +++ /dev/null @@ -1,181 +0,0 @@ -// -// 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. -// - -using System; -using System.Diagnostics; -using System.Net; -using System.Net.Sockets; -using Moq; -using OpenTelemetry.Trace; -using StackExchange.Redis; -using StackExchange.Redis.Profiling; -using Xunit; - -namespace OpenTelemetry.Instrumentation.StackExchangeRedis.Implementation -{ - [Collection("Redis")] - public class RedisProfilerEntryToActivityConverterTests : IDisposable - { - private readonly ConnectionMultiplexer connection; - private readonly IDisposable tracerProvider; - - public RedisProfilerEntryToActivityConverterTests() - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = false, - }; - connectionOptions.EndPoints.Add("localhost:6379"); - - this.connection = ConnectionMultiplexer.Connect(connectionOptions); - - this.tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddRedisInstrumentation(this.connection) - .Build(); - } - - public void Dispose() - { - this.tracerProvider.Dispose(); - this.connection.Dispose(); - GC.SuppressFinalize(this); - } - - [Fact] - public void ProfilerCommandToActivity_UsesCommandAsName() - { - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - profiledCommand.Setup(m => m.Command).Returns("SET"); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.Equal("SET", result.DisplayName); - } - - [Fact] - public void ProfilerCommandToActivity_UsesTimestampAsStartTime() - { - var now = DateTimeOffset.Now; - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(now.DateTime); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.Equal(now, result.StartTimeUtc); - } - - [Fact] - public void ProfilerCommandToActivity_SetsDbTypeAttributeAsRedis() - { - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributeDbSystem)); - Assert.Equal("redis", result.GetTagValue(SemanticConventions.AttributeDbSystem)); - } - - [Fact] - public void ProfilerCommandToActivity_UsesCommandAsDbStatementAttribute() - { - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - profiledCommand.Setup(m => m.Command).Returns("SET"); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributeDbStatement)); - Assert.Equal("SET", result.GetTagValue(SemanticConventions.AttributeDbStatement)); - } - - [Fact] - public void ProfilerCommandToActivity_UsesFlagsForFlagsAttribute() - { - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - var expectedFlags = CommandFlags.FireAndForget | - CommandFlags.NoRedirect; - profiledCommand.Setup(m => m.Flags).Returns(expectedFlags); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.NotNull(result.GetTagValue(StackExchangeRedisCallsInstrumentation.RedisFlagsKeyName)); - Assert.Equal("PreferMaster, FireAndForget, NoRedirect", result.GetTagValue(StackExchangeRedisCallsInstrumentation.RedisFlagsKeyName)); - } - - [Fact] - public void ProfilerCommandToActivity_UsesIpEndPointAsEndPoint() - { - long address = 1; - int port = 2; - - var activity = new Activity("redis-profiler"); - IPEndPoint ipLocalEndPoint = new IPEndPoint(address, port); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - profiledCommand.Setup(m => m.EndPoint).Returns(ipLocalEndPoint); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributeNetPeerIp)); - Assert.Equal($"{address}.0.0.0", result.GetTagValue(SemanticConventions.AttributeNetPeerIp)); - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributeNetPeerPort)); - Assert.Equal(port, result.GetTagValue(SemanticConventions.AttributeNetPeerPort)); - } - - [Fact] - public void ProfilerCommandToActivity_UsesDnsEndPointAsEndPoint() - { - var dnsEndPoint = new DnsEndPoint("https://opentelemetry.io/", 443); - - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - profiledCommand.Setup(m => m.EndPoint).Returns(dnsEndPoint); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributeNetPeerName)); - Assert.Equal(dnsEndPoint.Host, result.GetTagValue(SemanticConventions.AttributeNetPeerName)); - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributeNetPeerPort)); - Assert.Equal(dnsEndPoint.Port, result.GetTagValue(SemanticConventions.AttributeNetPeerPort)); - } - -#if !NETFRAMEWORK - [Fact] - public void ProfilerCommandToActivity_UsesOtherEndPointAsEndPoint() - { - var unixEndPoint = new UnixDomainSocketEndPoint("https://opentelemetry.io/"); - var activity = new Activity("redis-profiler"); - var profiledCommand = new Mock(); - profiledCommand.Setup(m => m.CommandCreated).Returns(DateTime.UtcNow); - profiledCommand.Setup(m => m.EndPoint).Returns(unixEndPoint); - - var result = RedisProfilerEntryToActivityConverter.ProfilerCommandToActivity(activity, profiledCommand.Object, new StackExchangeRedisCallsInstrumentationOptions()); - - Assert.NotNull(result.GetTagValue(SemanticConventions.AttributePeerService)); - Assert.Equal(unixEndPoint.ToString(), result.GetTagValue(SemanticConventions.AttributePeerService)); - } -#endif - } -} diff --git a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.csproj b/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.csproj deleted file mode 100644 index 4d80417bab2..00000000000 --- a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - Unit test project for OpenTelemetry StackExchangeRedis instrumentation - - net6.0;netcoreapp3.1 - $(TargetFrameworks);net462 - $(TARGET_FRAMEWORK) - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - diff --git a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/StackExchangeRedisCallsInstrumentationTests.cs b/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/StackExchangeRedisCallsInstrumentationTests.cs deleted file mode 100644 index 46a29aa7b67..00000000000 --- a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/StackExchangeRedisCallsInstrumentationTests.cs +++ /dev/null @@ -1,417 +0,0 @@ -// -// 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. -// -using System; -using System.Diagnostics; -using System.Net; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Moq; -using OpenTelemetry.Tests; -using OpenTelemetry.Trace; -using StackExchange.Redis; -using StackExchange.Redis.Profiling; -using Xunit; - -namespace OpenTelemetry.Instrumentation.StackExchangeRedis.Tests -{ - [Collection("Redis")] - public class StackExchangeRedisCallsInstrumentationTests - { - /* - To run the integration tests, set the OTEL_REDISENDPOINT machine-level environment variable to a valid Redis endpoint. - - To use Docker... - 1) Run: docker run -d --name redis -p 6379:6379 redis - 2) Set OTEL_REDISENDPOINT as: localhost:6379 - */ - - private const string RedisEndPointEnvVarName = "OTEL_REDISENDPOINT"; - private static readonly string RedisEndPoint = SkipUnlessEnvVarFoundTheoryAttribute.GetEnvironmentVariable(RedisEndPointEnvVarName); - - [Trait("CategoryName", "RedisIntegrationTests")] - [SkipUnlessEnvVarFoundTheory(RedisEndPointEnvVarName)] - [InlineData("value1")] - public void SuccessfulCommandTestWithKey(string value) - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = true, - }; - connectionOptions.EndPoints.Add(RedisEndPoint); - - using var connection = ConnectionMultiplexer.Connect(connectionOptions); - var db = connection.GetDatabase(); - db.KeyDelete("key1"); - - var activityProcessor = new Mock>(); - var sampler = new TestSampler(); - using (Sdk.CreateTracerProviderBuilder() - .AddProcessor(activityProcessor.Object) - .SetSampler(sampler) - .AddRedisInstrumentation(connection, c => c.SetVerboseDatabaseStatements = true) - .Build()) - { - var prepared = LuaScript.Prepare("redis.call('set', @key, @value)"); - db.ScriptEvaluate(prepared, new { key = (RedisKey)"mykey", value = 123 }); - - var redisValue = db.StringGet("key1"); - - Assert.False(redisValue.HasValue); - - bool set = db.StringSet("key1", value, TimeSpan.FromSeconds(60)); - - Assert.True(set); - - redisValue = db.StringGet("key1"); - - Assert.True(redisValue.HasValue); - Assert.Equal(value, redisValue.ToString()); - } - - // Disposing SDK should flush the Redis profiling session immediately. - - Assert.Equal(11, activityProcessor.Invocations.Count); - - var scriptActivity = (Activity)activityProcessor.Invocations[1].Arguments[0]; - Assert.Equal("EVAL", scriptActivity.DisplayName); - Assert.Equal("EVAL redis.call('set', ARGV[1], ARGV[2])", scriptActivity.GetTagValue(SemanticConventions.AttributeDbStatement)); - - VerifyActivityData((Activity)activityProcessor.Invocations[3].Arguments[0], false, connection.GetEndPoints()[0], true); - VerifyActivityData((Activity)activityProcessor.Invocations[5].Arguments[0], true, connection.GetEndPoints()[0], true); - VerifyActivityData((Activity)activityProcessor.Invocations[7].Arguments[0], false, connection.GetEndPoints()[0], true); - VerifySamplingParameters(sampler.LatestSamplingParameters); - } - - [Trait("CategoryName", "RedisIntegrationTests")] - [SkipUnlessEnvVarFoundTheory(RedisEndPointEnvVarName)] - [InlineData("value1")] - public void SuccessfulCommandTest(string value) - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = true, - }; - connectionOptions.EndPoints.Add(RedisEndPoint); - - using var connection = ConnectionMultiplexer.Connect(connectionOptions); - - var activityProcessor = new Mock>(); - var sampler = new TestSampler(); - using (Sdk.CreateTracerProviderBuilder() - .AddProcessor(activityProcessor.Object) - .SetSampler(sampler) - .AddRedisInstrumentation(connection, c => c.SetVerboseDatabaseStatements = false) - .Build()) - { - var db = connection.GetDatabase(); - - bool set = db.StringSet("key1", value, TimeSpan.FromSeconds(60)); - - Assert.True(set); - - var redisValue = db.StringGet("key1"); - - Assert.True(redisValue.HasValue); - Assert.Equal(value, redisValue.ToString()); - } - - // Disposing SDK should flush the Redis profiling session immediately. - - Assert.Equal(7, activityProcessor.Invocations.Count); - - VerifyActivityData((Activity)activityProcessor.Invocations[1].Arguments[0], true, connection.GetEndPoints()[0], false); - VerifyActivityData((Activity)activityProcessor.Invocations[3].Arguments[0], false, connection.GetEndPoints()[0], false); - VerifySamplingParameters(sampler.LatestSamplingParameters); - } - - [Fact] - public async void ProfilerSessionUsesTheSameDefault() - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = false, - }; - connectionOptions.EndPoints.Add("localhost:6379"); - - var connection = ConnectionMultiplexer.Connect(connectionOptions); - - using var instrumentation = new StackExchangeRedisCallsInstrumentation(connection, new StackExchangeRedisCallsInstrumentationOptions()); - var profilerFactory = instrumentation.GetProfilerSessionsFactory(); - var first = profilerFactory(); - var second = profilerFactory(); - ProfilingSession third = null; - await Task.Delay(1).ContinueWith((t) => { third = profilerFactory(); }); - Assert.Equal(first, second); - Assert.Equal(second, third); - } - - [Trait("CategoryName", "RedisIntegrationTests")] - [SkipUnlessEnvVarFoundTheory(RedisEndPointEnvVarName)] - [InlineData("value1")] - public void CanEnrichActivityFromCommand(string value) - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = true, - }; - connectionOptions.EndPoints.Add(RedisEndPoint); - - using var connection = ConnectionMultiplexer.Connect(connectionOptions); - - var activityProcessor = new Mock>(); - var sampler = new TestSampler(); - using (Sdk.CreateTracerProviderBuilder() - .AddProcessor(activityProcessor.Object) - .SetSampler(sampler) - .AddRedisInstrumentation(connection, c => c.Enrich = (activity, command) => - { - if (command.ElapsedTime < TimeSpan.FromMilliseconds(100)) - { - activity.AddTag("is_fast", true); - } - }) - .Build()) - { - var db = connection.GetDatabase(); - - bool set = db.StringSet("key1", value, TimeSpan.FromSeconds(60)); - - Assert.True(set); - - var redisValue = db.StringGet("key1"); - - Assert.True(redisValue.HasValue); - Assert.Equal(value, redisValue.ToString()); - } - - // Disposing SDK should flush the Redis profiling session immediately. - - Assert.Equal(7, activityProcessor.Invocations.Count); - - var setActivity = (Activity)activityProcessor.Invocations[1].Arguments[0]; - Assert.Equal(true, setActivity.GetTagValue("is_fast")); - var getActivity = (Activity)activityProcessor.Invocations[3].Arguments[0]; - Assert.Equal(true, getActivity.GetTagValue("is_fast")); - } - - [Fact] - public void CheckCacheIsFlushedProperly() - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = false, - }; - connectionOptions.EndPoints.Add("localhost:6379"); - - var connection = ConnectionMultiplexer.Connect(connectionOptions); - - using var instrumentation = new StackExchangeRedisCallsInstrumentation(connection, new StackExchangeRedisCallsInstrumentationOptions()); - var profilerFactory = instrumentation.GetProfilerSessionsFactory(); - - // start a root level activity - using Activity rootActivity = new Activity("Parent") - .SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded) - .Start(); - - Assert.NotNull(rootActivity.Id); - - // get an initial profiler from root activity - Activity.Current = rootActivity; - ProfilingSession profiler0 = profilerFactory(); - - // expect different result from synchronous child activity - ProfilingSession profiler1; - using (Activity.Current = new Activity("Child-Span-1").SetParentId(rootActivity.Id).Start()) - { - profiler1 = profilerFactory(); - Assert.NotSame(profiler0, profiler1); - } - - rootActivity.Stop(); - rootActivity.Dispose(); - - instrumentation.Flush(); - Assert.Empty(instrumentation.Cache); - } - - [Fact] - public async Task ProfilerSessionsHandleMultipleSpans() - { - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = false, - }; - connectionOptions.EndPoints.Add("localhost:6379"); - - var connection = ConnectionMultiplexer.Connect(connectionOptions); - - using var instrumentation = new StackExchangeRedisCallsInstrumentation(connection, new StackExchangeRedisCallsInstrumentationOptions()); - var profilerFactory = instrumentation.GetProfilerSessionsFactory(); - - // start a root level activity - using Activity rootActivity = new Activity("Parent") - .SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded) - .Start(); - - Assert.NotNull(rootActivity.Id); - - // get an initial profiler from root activity - Activity.Current = rootActivity; - ProfilingSession profiler0 = profilerFactory(); - - // expect different result from synchronous child activity - ProfilingSession profiler1; - using (Activity.Current = new Activity("Child-Span-1").SetParentId(rootActivity.Id).Start()) - { - profiler1 = profilerFactory(); - Assert.NotSame(profiler0, profiler1); - } - - Activity.Current = rootActivity; - - // expect different result from asynchronous child activity - using (Activity.Current = new Activity("Child-Span-2").SetParentId(rootActivity.Id).Start()) - { - // lose async context on purpose - await Task.Delay(100).ConfigureAwait(false); - - ProfilingSession profiler2 = profilerFactory(); - Assert.NotSame(profiler0, profiler2); - Assert.NotSame(profiler1, profiler2); - } - - Activity.Current = rootActivity; - - // ensure same result back in root activity - ProfilingSession profiles3 = profilerFactory(); - Assert.Same(profiler0, profiles3); - } - - [Fact] - public void StackExchangeRedis_BadArgs() - { - TracerProviderBuilder builder = null; - Assert.Throws(() => builder.AddRedisInstrumentation(null)); - - var activityProcessor = new Mock>(); - Assert.Throws(() => - Sdk.CreateTracerProviderBuilder() - .AddProcessor(activityProcessor.Object) - .AddRedisInstrumentation(null) - .Build()); - } - - [Fact] - public void StackExchangeRedis_DependencyInjection_Success() - { - bool connectionMultiplexerPickedFromDI = false; - bool optionsPickedFromDI = false; - - var connectionOptions = new ConfigurationOptions - { - AbortOnConnectFail = false, - }; - connectionOptions.EndPoints.Add("localhost"); - - var services = new ServiceCollection(); - services.AddSingleton((sp) => - { - connectionMultiplexerPickedFromDI = true; - return ConnectionMultiplexer.Connect(connectionOptions); - }); - services.Configure(options => - { - optionsPickedFromDI = true; - }); - services.AddOpenTelemetryTracing(builder => builder.AddRedisInstrumentation()); - - using var serviceProvider = services.BuildServiceProvider(); - - var tracerProvider = serviceProvider.GetRequiredService(); - - Assert.True(connectionMultiplexerPickedFromDI); - Assert.True(optionsPickedFromDI); - } - - [Fact] - public void StackExchangeRedis_DependencyInjection_Failure() - { - var services = new ServiceCollection(); - - services.AddOpenTelemetryTracing(builder => builder.AddRedisInstrumentation()); - - using var serviceProvider = services.BuildServiceProvider(); - - Assert.Throws(() => serviceProvider.GetRequiredService()); - } - - private static void VerifyActivityData(Activity activity, bool isSet, EndPoint endPoint, bool setCommandKey = false) - { - if (isSet) - { - Assert.Equal("SETEX", activity.DisplayName); - if (setCommandKey) - { - Assert.Equal("SETEX key1", activity.GetTagValue(SemanticConventions.AttributeDbStatement)); - } - else - { - Assert.Equal("SETEX", activity.GetTagValue(SemanticConventions.AttributeDbStatement)); - } - } - else - { - Assert.Equal("GET", activity.DisplayName); - if (setCommandKey) - { - Assert.Equal("GET key1", activity.GetTagValue(SemanticConventions.AttributeDbStatement)); - } - else - { - Assert.Equal("GET", activity.GetTagValue(SemanticConventions.AttributeDbStatement)); - } - } - - Assert.Equal(Status.Unset, activity.GetStatus()); - Assert.Equal("redis", activity.GetTagValue(SemanticConventions.AttributeDbSystem)); - Assert.Equal(0, activity.GetTagValue(StackExchangeRedisCallsInstrumentation.RedisDatabaseIndexKeyName)); - - if (endPoint is IPEndPoint ipEndPoint) - { - Assert.Equal(ipEndPoint.Address.ToString(), activity.GetTagValue(SemanticConventions.AttributeNetPeerIp)); - Assert.Equal(ipEndPoint.Port, activity.GetTagValue(SemanticConventions.AttributeNetPeerPort)); - } - else if (endPoint is DnsEndPoint dnsEndPoint) - { - Assert.Equal(dnsEndPoint.Host, activity.GetTagValue(SemanticConventions.AttributeNetPeerName)); - Assert.Equal(dnsEndPoint.Port, activity.GetTagValue(SemanticConventions.AttributeNetPeerPort)); - } - else - { - Assert.Equal(endPoint.ToString(), activity.GetTagValue(SemanticConventions.AttributePeerService)); - } - } - - private static void VerifySamplingParameters(SamplingParameters samplingParameters) - { - Assert.NotNull(samplingParameters.Tags); - Assert.Contains( - samplingParameters.Tags, - kvp => kvp.Key == SemanticConventions.AttributeDbSystem - && (string)kvp.Value == "redis"); - } - } -} diff --git a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/docker-compose.yml b/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/docker-compose.yml deleted file mode 100644 index 7004e679c00..00000000000 --- a/test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/docker-compose.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Start a redis container and then run OpenTelemetry redis integration tests. -# This should be run from the root of the repo: -# opentelemetry>docker-compose --file=test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/docker-compose.yml --project-directory=. up --exit-code-from=tests --build -version: '3.7' - -services: - redis: - image: redis - ports: - - "6379:6379" - - tests: - build: - context: . - dockerfile: ./test/OpenTelemetry.Instrumentation.StackExchangeRedis.Tests/Dockerfile - command: --TestCaseFilter:CategoryName=RedisIntegrationTests - environment: - - OTEL_REDISENDPOINT=redis:6379 - depends_on: - - redis diff --git a/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs b/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs index c5337ef49a6..841d4f293ad 100644 --- a/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs @@ -16,17 +16,19 @@ using System.Collections.Generic; using System.Diagnostics.Metrics; + using OpenTelemetry.Tests; + using Xunit; namespace OpenTelemetry.Metrics.Tests { public class InMemoryExporterTests { - [Fact(Skip = "To be run after https://github.com/open-telemetry/opentelemetry-dotnet/issues/2361 is fixed")] + [Fact] public void InMemoryExporterShouldDeepCopyMetricPoints() { - var exportedItems = new List(); + var exportedItems = new List(); using var meter = new Meter(Utils.GetCurrentMethodName()); using var meterProvider = Sdk.CreateMeterProviderBuilder() @@ -39,30 +41,29 @@ public void InMemoryExporterShouldDeepCopyMetricPoints() var counter = meter.CreateCounter("meter"); - // Emit 10 for the MetricPoint with a single key-vaue pair: ("tag1", "value1") + // TEST 1: Emit 10 for the MetricPoint with a single key-vaue pair: ("tag1", "value1") counter.Add(10, new KeyValuePair("tag1", "value1")); meterProvider.ForceFlush(); - var metric = exportedItems[0]; // Only one Metric object is added to the collection at this point - var metricPointsEnumerator = metric.GetMetricPoints().GetEnumerator(); - Assert.True(metricPointsEnumerator.MoveNext()); // One MetricPoint is emitted for the Metric - ref readonly var metricPointForFirstExport = ref metricPointsEnumerator.Current; - Assert.Equal(10, metricPointForFirstExport.GetSumLong()); + Assert.Single(exportedItems); + var metric1 = exportedItems[0]; // Only one Metric object is added to the collection at this point + Assert.Single(metric1.MetricPoints); + Assert.Equal(10, metric1.MetricPoints[0].GetSumLong()); - // Emit 25 for the MetricPoint with a single key-vaue pair: ("tag1", "value1") + // TEST 2: Emit 25 for the MetricPoint with a single key-vaue pair: ("tag1", "value1") counter.Add(25, new KeyValuePair("tag1", "value1")); meterProvider.ForceFlush(); - metric = exportedItems[1]; // Second Metric object is added to the collection at this point - metricPointsEnumerator = metric.GetMetricPoints().GetEnumerator(); - Assert.True(metricPointsEnumerator.MoveNext()); // One MetricPoint is emitted for the Metric - var metricPointForSecondExport = metricPointsEnumerator.Current; - Assert.Equal(25, metricPointForSecondExport.GetSumLong()); + Assert.Equal(2, exportedItems.Count); + var metric2 = exportedItems[1]; // Second Metric object is added to the collection at this point + Assert.Single(metric2.MetricPoints); + Assert.Equal(25, metric2.MetricPoints[0].GetSumLong()); - // MetricPoint.LongValue for the first exporter metric should still be 10 - Assert.Equal(10, metricPointForFirstExport.GetSumLong()); + // TEST 3: Verify first exported metric is unchanged + // MetricPoint.LongValue for the first exported metric should still be 10 + Assert.Equal(10, metric1.MetricPoints[0].GetSumLong()); } } } diff --git a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs index 3b70cf5f022..a4357f5e8bd 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs @@ -42,6 +42,39 @@ public MetricApiTest(ITestOutputHelper output) this.output = output; } + [Fact] + public void MeasurementWithNullValuedTag() + { + using var meter = new Meter(Utils.GetCurrentMethodName()); + var exportedItems = new List(); + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(exportedItems) + .Build(); + + var counter = meter.CreateCounter("myCounter"); + counter.Add(100, new KeyValuePair("tagWithNullValue", null)); + + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Single(exportedItems); + var metric = exportedItems[0]; + Assert.Equal("myCounter", metric.Name); + List metricPoints = new List(); + foreach (ref readonly var mp in metric.GetMetricPoints()) + { + metricPoints.Add(mp); + } + + Assert.Single(metricPoints); + var metricPoint = metricPoints[0]; + Assert.Equal(100, metricPoint.GetSumLong()); + Assert.Equal(1, metricPoint.Tags.Count); + var tagEnumerator = metricPoint.Tags.GetEnumerator(); + tagEnumerator.MoveNext(); + Assert.Equal("tagWithNullValue", tagEnumerator.Current.Key); + Assert.Null(tagEnumerator.Current.Value); + } + [Fact] public void ObserverCallbackTest() { diff --git a/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorTest.cs b/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorTest.cs index 33c6579d11c..67e24fa18fc 100644 --- a/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorTest.cs +++ b/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorTest.cs @@ -190,9 +190,8 @@ public void CheckExportForRecordingButNotSampledActivity() [Fact] public void CheckExportDrainsBatchOnFailure() { - using var exporter = new InMemoryExporter(null); using var processor = new BatchActivityExportProcessor( - exporter, + exporter: new FailureExporter(), maxQueueSize: 3, maxExportBatchSize: 3); @@ -208,5 +207,11 @@ public void CheckExportDrainsBatchOnFailure() Assert.Equal(3, processor.ProcessedCount); // Verify batch was drained even though nothing was exported. } + + private class FailureExporter : BaseExporter + where T : class + { + public override ExportResult Export(in Batch batch) => ExportResult.Failure; + } } } diff --git a/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs b/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs index 3778e7214bd..a18a24df015 100644 --- a/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs +++ b/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs @@ -222,6 +222,38 @@ public void TracerProviderSdkSamplerAttributesAreAppliedToActivity(SamplingDecis } } + [Fact] + public void TracerSdkSetsActivitySamplingResultAsPropagationWhenParentIsRemote() + { + var testSampler = new TestSampler(); + using var activitySource = new ActivitySource(ActivitySourceName); + using var tracerProvider = Sdk.CreateTracerProviderBuilder() + .AddSource(ActivitySourceName) + .SetSampler(testSampler) + .Build(); + + testSampler.SamplingAction = (samplingParameters) => + { + return new SamplingResult(SamplingDecision.Drop); + }; + + ActivityContext ctx = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, isRemote: true); + + using (var activity = activitySource.StartActivity("root", ActivityKind.Server, ctx)) + { + // Even if sampling returns false, for activities with remote parent, + // activity is still created with PropagationOnly. + Assert.NotNull(activity); + Assert.False(activity.IsAllDataRequested); + Assert.False(activity.Recorded); + + // This is not a root activity and parent is not remote. + // If sampling returns false, no activity is created at all. + using var innerActivity = activitySource.StartActivity("inner"); + Assert.Null(innerActivity); + } + } + [Fact] public void TracerSdkSetsActivitySamplingResultBasedOnSamplingDecision() { From 341fb7e69ff697905dcdb99dd911711f95c49ded Mon Sep 17 00:00:00 2001 From: Jacob Jago Date: Wed, 8 Jun 2022 09:23:01 -0600 Subject: [PATCH 4/5] moved jaegerpropagator comment to unreleased --- src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md index a9a12f2cb92..1072badd28a 100644 --- a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* Added JaegerPropagator ([1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881)) + ## 1.3.0 Released 2022-Jun-03 @@ -15,5 +17,3 @@ Released 2022-June-1 * Initial release. This has been ported as is from [OpenTelemetry.Api](../OpenTelemetry.Api/README.md) package. - -* Added JaegerPropagator ([1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881)) From 91415d00ec9c450853f3ee27c0540cf7be2e6bb1 Mon Sep 17 00:00:00 2001 From: tyler jago Date: Wed, 8 Jun 2022 09:43:05 -0600 Subject: [PATCH 5/5] Update src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Robert Pająk --- src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md index 1072badd28a..b8ded0360f5 100644 --- a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md @@ -2,7 +2,8 @@ ## Unreleased -* Added JaegerPropagator ([1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881)) +* Add `JaegerPropagator`. + ([1881](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1881)) ## 1.3.0