diff --git a/Directory.Packages.props b/Directory.Packages.props index f9e13e73ee4..a3bf3bb80b5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,7 +2,6 @@ true - @@ -26,11 +25,10 @@ - - + + - diff --git a/src/OpenTelemetry.Exporter.Console/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Console/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index e69de29bb2d..db4a2abc8a8 100644 --- a/src/OpenTelemetry.Exporter.Console/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Console/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1,6 @@ +OpenTelemetry.Exporter.ConsoleActivityJsonExporter +OpenTelemetry.Exporter.ConsoleActivityJsonExporter.ConsoleActivityJsonExporter(OpenTelemetry.Exporter.ConsoleExporterOptions options) -> void +override OpenTelemetry.Exporter.ConsoleActivityJsonExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult +static OpenTelemetry.Trace.ConsoleExporterHelperExtensions.AddConsoleJsonExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.ConsoleExporterHelperExtensions.AddConsoleJsonExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.ConsoleExporterHelperExtensions.AddConsoleJsonExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleActivityJsonExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleActivityJsonExporter.cs new file mode 100644 index 00000000000..8526e408310 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Console/ConsoleActivityJsonExporter.cs @@ -0,0 +1,160 @@ +using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Serialization; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; + +namespace OpenTelemetry.Exporter +{ + public class ConsoleActivityJsonExporter : ConsoleExporter + { + public ConsoleActivityJsonExporter(ConsoleExporterOptions options) + : base(options) + { + } + + public override ExportResult Export(in Batch batch) + { + foreach (var activity in batch) + { + dynamic activityBuilder = new System.Dynamic.ExpandoObject(); + + + activityBuilder.TraceId = activity.TraceId.ToString(); + activityBuilder.SpanId = activity.SpanId.ToString(); + activityBuilder.ActivityTraceFlags = activity.ActivityTraceFlags; + activityBuilder.ActivitySourceName = activity.Source.Name; + activityBuilder.DisplayName = activity.DisplayName; + activityBuilder.Kind = activity.Kind; + activityBuilder.StartTime = activity.StartTimeUtc.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); + activityBuilder.Duration = activity.Duration; + + if (!string.IsNullOrEmpty(activity.TraceStateString)) + { + activityBuilder.TraceState = activity.TraceStateString; + } + + if (activity.ParentSpanId != default) + { + activityBuilder.ParentSpanId = activity.ParentSpanId.ToString(); + } + + var statusCode = string.Empty; + var statusDesc = string.Empty; + + if (activity.TagObjects.Any()) + { + foreach (ref readonly var tag in activity.EnumerateTagObjects()) + { + if (tag.Key == SpanAttributeConstants.StatusCodeKey) + { + statusCode = tag.Value as string; + continue; + } + + if (tag.Key == SpanAttributeConstants.StatusDescriptionKey) + { + statusDesc = tag.Value as string; + continue; + } + + if (ConsoleTagTransformer.Instance.TryTransformTag(tag, out var result)) + { + activityBuilder.Tags = result; + } + } + } + + if (activity.Status != ActivityStatusCode.Unset) + { + activityBuilder.StatusCode = activity.Status; + + if (!string.IsNullOrEmpty(activity.StatusDescription)) + { + activityBuilder.StatusDescription = activity.StatusDescription; + } + } + else if (!string.IsNullOrEmpty(statusCode)) + { + activityBuilder.StatusCode = statusCode; + if (!string.IsNullOrEmpty(statusDesc)) + { + activityBuilder.StatusDescription = statusDesc; + } + } + + if (activity.Events.Any()) + { + activityBuilder.Events = new List(); + + foreach (ref readonly var activityEvent in activity.EnumerateEvents()) + { + dynamic activityEventBuilder = new System.Dynamic.ExpandoObject(); + + activityEventBuilder.Name = activityEvent.Name; + activityEventBuilder.Timestamp = activityEvent.Timestamp; + + foreach (ref readonly var attribute in activityEvent.EnumerateTagObjects()) + { + if (ConsoleTagTransformer.Instance.TryTransformTag(attribute, out var result)) + { + activityEventBuilder.Tags = result; + } + } + + activityBuilder.Events.add(activityEventBuilder); + } + } + + if (activity.Links.Any()) + { + activityBuilder.Links = new List(); + + foreach (ref readonly var activityLink in activity.EnumerateLinks()) + { + dynamic activityLinkBuilder = new System.Dynamic.ExpandoObject(); + + activityLinkBuilder.TraceId = activityLink.Context.TraceId.ToString(); + activityLinkBuilder.SpanId = activityLink.Context.SpanId.ToString(); + + foreach (ref readonly var attribute in activityLink.EnumerateTagObjects()) + { + if (ConsoleTagTransformer.Instance.TryTransformTag(attribute, out var result)) + { + activityLinkBuilder.Tags = result; + } + } + + activityBuilder.Links.add(activityLinkBuilder); + } + } + + var resource = this.ParentProvider.GetResource(); + if (resource != Resource.Empty) + { + + foreach (var resourceAttribute in resource.Attributes) + { + if (ConsoleTagTransformer.Instance.TryTransformTag(resourceAttribute, out var result)) + { + activityBuilder.Attributes = result; + } + } + } + + var options = new JsonSerializerOptions + { + WriteIndented = false, + ReferenceHandler = ReferenceHandler.IgnoreCycles, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + string json = JsonSerializer.Serialize(activityBuilder, options); + + this.WriteLine(json); + } + + return ExportResult.Success; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs index 08330a0a9d4..ebc06096762 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs @@ -68,5 +68,52 @@ public static TracerProviderBuilder AddConsoleExporter( return new SimpleActivityExportProcessor(new ConsoleActivityExporter(options)); }); } + + /// + /// Adds Console JSON exporter to the TracerProvider. + /// + /// builder to use. + /// The instance of to chain the calls. + public static TracerProviderBuilder AddConsoleJsonExporter(this TracerProviderBuilder builder) + => AddConsoleJsonExporter(builder, name: null, configure: null); + + /// + /// Adds Console JSON exporter to the TracerProvider. + /// + /// builder to use. + /// Callback action for configuring . + /// The instance of to chain the calls. + public static TracerProviderBuilder AddConsoleJsonExporter(this TracerProviderBuilder builder, Action configure) + => AddConsoleJsonExporter(builder, name: null, configure); + + + /// + /// Adds Console JSON exporter to the TracerProvider. + /// + /// builder to use. + /// Name which is used when retrieving options. + /// Callback action for configuring . + /// The instance of to chain the calls. + public static TracerProviderBuilder AddConsoleJsonExporter( + this TracerProviderBuilder builder, + string name, + Action configure) + { + Guard.ThrowIfNull(builder); + + name ??= Options.DefaultName; + + if (configure != null) + { + builder.ConfigureServices(services => services.Configure(name, configure)); + } + + return builder.AddProcessor(sp => + { + var options = sp.GetRequiredService>().Get(name); + + return new SimpleActivityExportProcessor(new ConsoleActivityJsonExporter(options)); + }); + } } }