diff --git a/.github/workflows/apicompatibility.yml b/.github/workflows/apicompatibility.yml index 2404c47d523..8eb8eb4e5a7 100644 --- a/.github/workflows/apicompatibility.yml +++ b/.github/workflows/apicompatibility.yml @@ -2,7 +2,7 @@ name: API Compatibility on: pull_request: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index bec49f1128c..a73663909da 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -2,11 +2,11 @@ name: Code Coverage on: push: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' pull_request: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' diff --git a/.github/workflows/docfx.yml b/.github/workflows/docfx.yml index b183f85311c..df4e37e9f08 100644 --- a/.github/workflows/docfx.yml +++ b/.github/workflows/docfx.yml @@ -2,9 +2,9 @@ name: docfx on: push: - branches: [ main ] + branches: [ 'main*' ] pull_request: - branches: [ main ] + branches: [ 'main*' ] jobs: build: diff --git a/.github/workflows/dotnet-format-md.yml b/.github/workflows/dotnet-format-md.yml index be810e6c827..d35d16849bb 100644 --- a/.github/workflows/dotnet-format-md.yml +++ b/.github/workflows/dotnet-format-md.yml @@ -9,7 +9,7 @@ name: dotnet format on: pull_request: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.cs' - '.editorconfig' diff --git a/.github/workflows/dotnet-format.yml b/.github/workflows/dotnet-format.yml index 6c9ccdc685f..7bbcac00d2d 100644 --- a/.github/workflows/dotnet-format.yml +++ b/.github/workflows/dotnet-format.yml @@ -2,12 +2,12 @@ name: dotnet format on: push: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.cs' - '.editorconfig' pull_request: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.cs' - '.editorconfig' diff --git a/.github/workflows/integration-md.yml b/.github/workflows/integration-md.yml index 3bcb0099255..54c3ad37e5d 100644 --- a/.github/workflows/integration-md.yml +++ b/.github/workflows/integration-md.yml @@ -9,7 +9,7 @@ name: Integration Tests on: pull_request: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.md' diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 8133308e7d3..13a1968abd7 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -2,11 +2,11 @@ name: Integration Tests on: push: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' pull_request: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' diff --git a/.github/workflows/linux-ci-md.yml b/.github/workflows/linux-ci-md.yml index a4358d1b90c..5b7008872e4 100644 --- a/.github/workflows/linux-ci-md.yml +++ b/.github/workflows/linux-ci-md.yml @@ -9,7 +9,7 @@ name: Linux on: pull_request: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.md' diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index ea89eddc381..cf4a881aac2 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -2,11 +2,11 @@ name: Linux on: push: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' pull_request: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml index 97f85f9e2b4..643c5f6f1d8 100644 --- a/.github/workflows/markdownlint.yml +++ b/.github/workflows/markdownlint.yml @@ -2,11 +2,11 @@ name: markdownlint on: push: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.md' pull_request: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.md' diff --git a/.github/workflows/sanitycheck.yml b/.github/workflows/sanitycheck.yml index a52563198e4..d452206e4bf 100644 --- a/.github/workflows/sanitycheck.yml +++ b/.github/workflows/sanitycheck.yml @@ -2,9 +2,9 @@ name: sanitycheck on: push: - branches: [ main ] + branches: [ 'main*' ] pull_request: - branches: [ main ] + branches: [ 'main*' ] jobs: misspell: diff --git a/.github/workflows/windows-ci-md.yml b/.github/workflows/windows-ci-md.yml index 63cf326b1da..2a241f170be 100644 --- a/.github/workflows/windows-ci-md.yml +++ b/.github/workflows/windows-ci-md.yml @@ -9,7 +9,7 @@ name: Windows on: pull_request: - branches: [ main ] + branches: [ 'main*' ] paths: - '**.md' diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 303c2b0e173..643ce43c841 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -2,11 +2,11 @@ name: Windows on: push: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' pull_request: - branches: [ main ] + branches: [ 'main*' ] paths-ignore: - '**.md' diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index ec895d0d87a..5d57b8fb892 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -234,6 +234,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Tests.Stress. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.AspNetCore", "test\TestApp.AspNetCore\TestApp.AspNetCore.csproj", "{5FDAF679-DE5A-4C73-A49B-8ABCF2399229}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.LoggingExtensions", "examples\LoggingExtensions\Examples.LoggingExtensions.csproj", "{7642798D-12D4-403A-BB92-B6BEF67C9D4F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.EventSource", "src\OpenTelemetry.Extensions.EventSource\OpenTelemetry.Extensions.EventSource.csproj", "{E55029E5-46B5-46E5-9BB3-CD5CE63E16CB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Serilog", "src\OpenTelemetry.Extensions.Serilog\OpenTelemetry.Extensions.Serilog.csproj", "{CB55CD2E-449C-44A2-A7CA-3C701B533F16}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.EventSource.Tests", "test\OpenTelemetry.Extensions.EventSource.Tests\OpenTelemetry.Extensions.EventSource.Tests.csproj", "{2A896854-8537-4BD6-8E1C-2B66B1160258}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Serilog.Tests", "test\OpenTelemetry.Extensions.Serilog.Tests\OpenTelemetry.Extensions.Serilog.Tests.csproj", "{3B3C3571-6116-49D6-B28F-2A541E003577}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -476,6 +486,26 @@ Global {5FDAF679-DE5A-4C73-A49B-8ABCF2399229}.Debug|Any CPU.Build.0 = Debug|Any CPU {5FDAF679-DE5A-4C73-A49B-8ABCF2399229}.Release|Any CPU.ActiveCfg = Release|Any CPU {5FDAF679-DE5A-4C73-A49B-8ABCF2399229}.Release|Any CPU.Build.0 = Release|Any CPU + {7642798D-12D4-403A-BB92-B6BEF67C9D4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7642798D-12D4-403A-BB92-B6BEF67C9D4F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7642798D-12D4-403A-BB92-B6BEF67C9D4F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7642798D-12D4-403A-BB92-B6BEF67C9D4F}.Release|Any CPU.Build.0 = Release|Any CPU + {E55029E5-46B5-46E5-9BB3-CD5CE63E16CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E55029E5-46B5-46E5-9BB3-CD5CE63E16CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E55029E5-46B5-46E5-9BB3-CD5CE63E16CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E55029E5-46B5-46E5-9BB3-CD5CE63E16CB}.Release|Any CPU.Build.0 = Release|Any CPU + {CB55CD2E-449C-44A2-A7CA-3C701B533F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB55CD2E-449C-44A2-A7CA-3C701B533F16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB55CD2E-449C-44A2-A7CA-3C701B533F16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB55CD2E-449C-44A2-A7CA-3C701B533F16}.Release|Any CPU.Build.0 = Release|Any CPU + {2A896854-8537-4BD6-8E1C-2B66B1160258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A896854-8537-4BD6-8E1C-2B66B1160258}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A896854-8537-4BD6-8E1C-2B66B1160258}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A896854-8537-4BD6-8E1C-2B66B1160258}.Release|Any CPU.Build.0 = Release|Any CPU + {3B3C3571-6116-49D6-B28F-2A541E003577}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B3C3571-6116-49D6-B28F-2A541E003577}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B3C3571-6116-49D6-B28F-2A541E003577}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B3C3571-6116-49D6-B28F-2A541E003577}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -512,6 +542,7 @@ Global {6C7A1595-36D6-4229-BBB5-5A6B5791791D} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} {9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} {5FDAF679-DE5A-4C73-A49B-8ABCF2399229} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F} + {7642798D-12D4-403A-BB92-B6BEF67C9D4F} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} diff --git a/build/Common.props b/build/Common.props index 8a5640bef03..deed26cd9ca 100644 --- a/build/Common.props +++ b/build/Common.props @@ -38,7 +38,7 @@ [1.0.0,2.0) [1.0.0,2.0) [0.12.1,0.13) - 1.3.0 + 1.3.1 [2.8.0,3.0) [1.2.0-beta.435,2.0) 1.4.0 diff --git a/docs/logs/correlation/Program.cs b/docs/logs/correlation/Program.cs index 722e66347e6..a6c22686fd6 100644 --- a/docs/logs/correlation/Program.cs +++ b/docs/logs/correlation/Program.cs @@ -32,10 +32,7 @@ public static void Main() // Setup Logging using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddConsoleExporter(); - }); + builder.AddOpenTelemetry().AddConsoleExporter(); }); var logger = loggerFactory.CreateLogger(); diff --git a/docs/logs/customizing-the-sdk/Program.cs b/docs/logs/customizing-the-sdk/Program.cs index b6b3afd07d8..900e28341ce 100644 --- a/docs/logs/customizing-the-sdk/Program.cs +++ b/docs/logs/customizing-the-sdk/Program.cs @@ -27,12 +27,10 @@ public static void Main() { using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.IncludeScopes = true; - options.ConfigureResource(r => r.AddService(serviceName: "MyService", serviceVersion: "1.0.0")); - options.AddConsoleExporter(); - }); + builder + .AddOpenTelemetry(options => options.IncludeScopes = true) + .ConfigureResource(r => r.AddService(serviceName: "MyService", serviceVersion: "1.0.0")) + .AddConsoleExporter(); }); var logger = loggerFactory.CreateLogger(); diff --git a/docs/logs/extending-the-sdk/LoggerExtensions.cs b/docs/logs/extending-the-sdk/LoggerExtensions.cs index 644d711c1a0..f32063db49b 100644 --- a/docs/logs/extending-the-sdk/LoggerExtensions.cs +++ b/docs/logs/extending-the-sdk/LoggerExtensions.cs @@ -20,13 +20,13 @@ internal static class LoggerExtensions { - public static OpenTelemetryLoggerOptions AddMyExporter(this OpenTelemetryLoggerOptions options) + public static LoggerProviderBuilder AddMyExporter(this LoggerProviderBuilder builder) { - if (options == null) + if (builder == null) { - throw new ArgumentNullException(nameof(options)); + throw new ArgumentNullException(nameof(builder)); } - return options.AddProcessor(new BatchLogRecordExportProcessor(new MyExporter())); + return builder.AddProcessor(new BatchLogRecordExportProcessor(new MyExporter())); } } diff --git a/docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs b/docs/logs/extending-the-sdk/MyRedactedAttributeList.cs similarity index 59% rename from docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs rename to docs/logs/extending-the-sdk/MyRedactedAttributeList.cs index 4e5f3107460..fa9e96c6379 100644 --- a/docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs +++ b/docs/logs/extending-the-sdk/MyRedactedAttributeList.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,32 +17,38 @@ using System.Collections; using System.Collections.Generic; -internal class MyClassWithRedactionEnumerator : IReadOnlyList> +internal class MyRedactedAttributeList : IReadOnlyList> { - private readonly IReadOnlyList> state; + private readonly IReadOnlyList> attributes; - public MyClassWithRedactionEnumerator(IReadOnlyList> state) + public MyRedactedAttributeList(IReadOnlyList> attributes) { - this.state = state; + this.attributes = attributes; } - public int Count => this.state.Count; + public int Count => this.attributes.Count; - public KeyValuePair this[int index] => this.state[index]; - - public IEnumerator> GetEnumerator() + public KeyValuePair this[int index] { - foreach (var entry in this.state) + get { - var entryVal = entry.Value; + var item = this.attributes[index]; + + var entryVal = item.Value; if (entryVal != null && entryVal.ToString() != null && entryVal.ToString().Contains("")) { - yield return new KeyValuePair(entry.Key, "newRedactedValueHere"); - } - else - { - yield return entry; + return new KeyValuePair(item.Key, "newRedactedValueHere"); } + + return item; + } + } + + public IEnumerator> GetEnumerator() + { + for (var i = 0; i < this.Count; i++) + { + yield return this[i]; } } diff --git a/docs/logs/extending-the-sdk/MyRedactionProcessor.cs b/docs/logs/extending-the-sdk/MyRedactionProcessor.cs index 2ad8371ae69..2c8f5bf00cc 100644 --- a/docs/logs/extending-the-sdk/MyRedactionProcessor.cs +++ b/docs/logs/extending-the-sdk/MyRedactionProcessor.cs @@ -14,7 +14,6 @@ // limitations under the License. // -using System.Collections.Generic; using OpenTelemetry; using OpenTelemetry.Logs; @@ -22,9 +21,9 @@ internal class MyRedactionProcessor : BaseProcessor { public override void OnEnd(LogRecord logRecord) { - if (logRecord.State is IReadOnlyList> listOfKvp) + if (logRecord.Attributes != null) { - logRecord.State = new MyClassWithRedactionEnumerator(listOfKvp); + logRecord.Attributes = new MyRedactedAttributeList(logRecord.Attributes); } } } diff --git a/docs/logs/extending-the-sdk/Program.cs b/docs/logs/extending-the-sdk/Program.cs index 2ea9dad4953..d5ab961fe1c 100644 --- a/docs/logs/extending-the-sdk/Program.cs +++ b/docs/logs/extending-the-sdk/Program.cs @@ -17,6 +17,7 @@ using System.Collections.Generic; using Microsoft.Extensions.Logging; using OpenTelemetry; +using OpenTelemetry.Logs; namespace ExtendingTheSdk; @@ -24,16 +25,13 @@ public class Program { public static void Main() { - using var loggerFactory = LoggerFactory.Create(builder => - builder.AddOpenTelemetry(options => - { - options.IncludeScopes = true; - options.AddProcessor(new MyRedactionProcessor()) - .AddProcessor(new MyProcessor("ProcessorA")) - .AddProcessor(new MyProcessor("ProcessorB")) - .AddProcessor(new SimpleLogRecordExportProcessor(new MyExporter("ExporterX"))) - .AddMyExporter(); - })); + using var loggerFactory = LoggerFactory.Create(builder => builder + .AddOpenTelemetry(options => options.IncludeScopes = true) + .AddProcessor(new MyRedactionProcessor()) + .AddProcessor(new MyProcessor("ProcessorA")) + .AddProcessor(new MyProcessor("ProcessorB")) + .AddProcessor(new SimpleLogRecordExportProcessor(new MyExporter("ExporterX"))) + .AddMyExporter()); var logger = loggerFactory.CreateLogger(); diff --git a/docs/logs/getting-started/Program.cs b/docs/logs/getting-started/Program.cs index d13ba546b4b..7f76f13899e 100644 --- a/docs/logs/getting-started/Program.cs +++ b/docs/logs/getting-started/Program.cs @@ -25,10 +25,7 @@ public static void Main() { using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddConsoleExporter(); - }); + builder.AddOpenTelemetry().AddConsoleExporter(); }); var logger = loggerFactory.CreateLogger(); diff --git a/docs/logs/source-generation/Program.cs b/docs/logs/source-generation/Program.cs index 42c0e41ec3a..63f82951029 100644 --- a/docs/logs/source-generation/Program.cs +++ b/docs/logs/source-generation/Program.cs @@ -23,16 +23,13 @@ public class Program { public static void Main() { - using var loggerFactory = LoggerFactory.Create(builder => - { - builder.AddOpenTelemetry(options => + using var loggerFactory = LoggerFactory.Create(builder => builder + .AddOpenTelemetry(options => { options.IncludeScopes = true; - options.ParseStateValues = true; options.IncludeFormattedMessage = true; - options.AddConsoleExporter(); - }); - }); + }) + .AddConsoleExporter()); var logger = loggerFactory.CreateLogger(); diff --git a/examples/AspNetCore/Program.cs b/examples/AspNetCore/Program.cs index e070011daa7..870626f5c31 100644 --- a/examples/AspNetCore/Program.cs +++ b/examples/AspNetCore/Program.cs @@ -87,25 +87,25 @@ // Logging builder.Logging.ClearProviders(); -builder.Logging.AddOpenTelemetry(options => -{ - options.ConfigureResource(configureResource); +// Note: See appsettings.json Logging:OpenTelemetry section for OpenTelemetryLoggerOptions bindings. +var loggerBuilder = builder.Logging.AddOpenTelemetry(); - // Switch between Console/OTLP by setting UseLogExporter in appsettings.json. - var logExporter = builder.Configuration.GetValue("UseLogExporter").ToLowerInvariant(); - switch (logExporter) - { - case "otlp": - options.AddOtlpExporter(otlpOptions => - { - otlpOptions.Endpoint = new Uri(builder.Configuration.GetValue("Otlp:Endpoint")); - }); - break; - default: - options.AddConsoleExporter(); - break; - } -}); +loggerBuilder.ConfigureResource(configureResource); + +// Switch between Console/OTLP by setting UseLogExporter in appsettings.json. +var logExporter = builder.Configuration.GetValue("UseLogExporter").ToLowerInvariant(); +switch (logExporter) +{ + case "otlp": + loggerBuilder.AddOtlpExporter(otlpOptions => + { + otlpOptions.Endpoint = new Uri(builder.Configuration.GetValue("Otlp:Endpoint")); + }); + break; + default: + loggerBuilder.AddConsoleExporter(); + break; +} builder.Services.Configure(opt => { diff --git a/examples/AspNetCore/appsettings.json b/examples/AspNetCore/appsettings.json index e2826c577b6..b85fb8dd5cb 100644 --- a/examples/AspNetCore/appsettings.json +++ b/examples/AspNetCore/appsettings.json @@ -4,6 +4,13 @@ "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" + }, + "OpenTelemetry": { + "IncludeFormattedMessage": false, + "IncludeScopes": false, + "IncludeState": true, + "ParseStateValues": false, + "IncludeTraceState": false } }, "AllowedHosts": "*", diff --git a/examples/LoggingExtensions/ExampleEventSource.cs b/examples/LoggingExtensions/ExampleEventSource.cs new file mode 100644 index 00000000000..7fa0b8cea95 --- /dev/null +++ b/examples/LoggingExtensions/ExampleEventSource.cs @@ -0,0 +1,33 @@ +// +// 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.Diagnostics.Tracing; + +namespace Examples.LoggingExtensions; + +[EventSource(Name = EventSourceName)] +internal sealed class ExampleEventSource : EventSource +{ + public const string EventSourceName = "OpenTelemetry-ExampleEventSource"; + + public static ExampleEventSource Log { get; } = new(); + + [Event(1, Message = "Example event written with '{0}' reason", Level = EventLevel.Informational)] + public void ExampleEvent(string reason) + { + this.WriteEvent(1, reason); + } +} diff --git a/examples/LoggingExtensions/Examples.LoggingExtensions.csproj b/examples/LoggingExtensions/Examples.LoggingExtensions.csproj new file mode 100644 index 00000000000..892a652ac78 --- /dev/null +++ b/examples/LoggingExtensions/Examples.LoggingExtensions.csproj @@ -0,0 +1,16 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + diff --git a/examples/LoggingExtensions/Program.cs b/examples/LoggingExtensions/Program.cs new file mode 100644 index 00000000000..7f3356836d6 --- /dev/null +++ b/examples/LoggingExtensions/Program.cs @@ -0,0 +1,54 @@ +// +// 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.Diagnostics.Tracing; +using Examples.LoggingExtensions; +using OpenTelemetry; +using OpenTelemetry.Logs; +using OpenTelemetry.Resources; +using Serilog; + +var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .ConfigureResource(builder => builder.AddService("Examples.LoggingExtensions")) + .AddConsoleExporter() + .Build(); + +// Creates an OpenTelemetryEventSourceLogEmitter for routing ExampleEventSource +// events into logs +using var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + loggerProvider, // <- Events will be written to loggerProvider + (name) => name == ExampleEventSource.EventSourceName ? EventLevel.Informational : null, + disposeProvider: false); // <- Do not dispose the provider with OpenTelemetryEventSourceLogEmitter since in this case it is shared with Serilog + +// Configure Serilog global logger +Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry( + loggerProvider, // <- Register OpenTelemetry Serilog sink writing to loggerProvider + disposeProvider: false) // <- Do not dispose the provider with Serilog since in this case it is shared with OpenTelemetryEventSourceLogEmitter + .CreateLogger(); + +ExampleEventSource.Log.ExampleEvent("Startup complete"); + +// Note: Serilog ForContext API is used to set "CategoryName" on log messages +ILogger programLogger = Log.Logger.ForContext(); + +programLogger.Information("Application started {Greeting} {Location}", "Hello", "World"); + +// Note: For Serilog this call flushes all logs +Log.CloseAndFlush(); + +// Manually dispose loggerProvider since it is being shared +loggerProvider.Dispose(); diff --git a/examples/LoggingExtensions/README.md b/examples/LoggingExtensions/README.md new file mode 100644 index 00000000000..adbb1df5b7c --- /dev/null +++ b/examples/LoggingExtensions/README.md @@ -0,0 +1,10 @@ +# OpenTelemetry Logging Extensions Example + +This project contains examples of the `LogEmitter` API being used to extend +existing logging platforms to write into OpenTelemetry logs. + +* Serilog: Using OpenTelemetry.Extensions.Serilog + +## References + +* [OpenTelemetry Project](https://opentelemetry.io/) diff --git a/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Shipped.txt index f375357a7c7..f4de20917f9 100644 --- a/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Shipped.txt @@ -1,44 +1,44 @@ -abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Fields.get -> System.Collections.Generic.ISet -abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void abstract OpenTelemetry.Context.RuntimeContextSlot.Get() -> T abstract OpenTelemetry.Context.RuntimeContextSlot.Set(T value) -> void -abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder -abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder -abstract OpenTelemetry.Trace.TracerProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder -abstract OpenTelemetry.Trace.TracerProviderBuilder.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder -abstract OpenTelemetry.Trace.TracerProviderBuilder.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder OpenTelemetry.ActivityContextExtensions OpenTelemetry.Baggage OpenTelemetry.Baggage.Baggage() -> void OpenTelemetry.Baggage.ClearBaggage() -> OpenTelemetry.Baggage OpenTelemetry.Baggage.Count.get -> int OpenTelemetry.Baggage.Equals(OpenTelemetry.Baggage other) -> bool -OpenTelemetry.Baggage.GetBaggage() -> System.Collections.Generic.IReadOnlyDictionary -OpenTelemetry.Baggage.GetBaggage(string name) -> string -OpenTelemetry.Baggage.GetEnumerator() -> System.Collections.Generic.Dictionary.Enumerator -OpenTelemetry.Baggage.RemoveBaggage(string name) -> OpenTelemetry.Baggage -OpenTelemetry.Baggage.SetBaggage(params System.Collections.Generic.KeyValuePair[] baggageItems) -> OpenTelemetry.Baggage -OpenTelemetry.Baggage.SetBaggage(string name, string value) -> OpenTelemetry.Baggage -OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.GetBaggage() -> System.Collections.Generic.IReadOnlyDictionary +~OpenTelemetry.Baggage.GetBaggage(string name) -> string +~OpenTelemetry.Baggage.GetEnumerator() -> System.Collections.Generic.Dictionary.Enumerator +~OpenTelemetry.Baggage.RemoveBaggage(string name) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(params System.Collections.Generic.KeyValuePair[] baggageItems) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(string name, string value) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems) -> OpenTelemetry.Baggage OpenTelemetry.BaseProvider OpenTelemetry.BaseProvider.~BaseProvider() -> void OpenTelemetry.BaseProvider.BaseProvider() -> void OpenTelemetry.BaseProvider.Dispose() -> void OpenTelemetry.Context.AsyncLocalRuntimeContextSlot -OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.AsyncLocalRuntimeContextSlot(string name) -> void -OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.get -> object -OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.set -> void +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.AsyncLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.set -> void OpenTelemetry.Context.IRuntimeContextSlotValueAccessor -OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.get -> object -OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.set -> void +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.get -> object +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.set -> void OpenTelemetry.Context.Propagation.B3Propagator OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator() -> void OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator(bool singleHeader) -> void OpenTelemetry.Context.Propagation.BaggagePropagator OpenTelemetry.Context.Propagation.BaggagePropagator.BaggagePropagator() -> void OpenTelemetry.Context.Propagation.CompositeTextMapPropagator -OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.CompositeTextMapPropagator(System.Collections.Generic.IEnumerable propagators) -> void +~OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.CompositeTextMapPropagator(System.Collections.Generic.IEnumerable propagators) -> void OpenTelemetry.Context.Propagation.PropagationContext OpenTelemetry.Context.Propagation.PropagationContext.ActivityContext.get -> System.Diagnostics.ActivityContext OpenTelemetry.Context.Propagation.PropagationContext.Baggage.get -> OpenTelemetry.Baggage @@ -51,56 +51,56 @@ OpenTelemetry.Context.Propagation.TextMapPropagator.TextMapPropagator() -> void OpenTelemetry.Context.Propagation.TraceContextPropagator OpenTelemetry.Context.Propagation.TraceContextPropagator.TraceContextPropagator() -> void OpenTelemetry.Context.RemotingRuntimeContextSlot -OpenTelemetry.Context.RemotingRuntimeContextSlot.RemotingRuntimeContextSlot(string name) -> void -OpenTelemetry.Context.RemotingRuntimeContextSlot.Value.get -> object -OpenTelemetry.Context.RemotingRuntimeContextSlot.Value.set -> void +~OpenTelemetry.Context.RemotingRuntimeContextSlot.RemotingRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.RemotingRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.RemotingRuntimeContextSlot.Value.set -> void OpenTelemetry.Context.RuntimeContext OpenTelemetry.Context.RuntimeContextSlot OpenTelemetry.Context.RuntimeContextSlot.Dispose() -> void -OpenTelemetry.Context.RuntimeContextSlot.Name.get -> string -OpenTelemetry.Context.RuntimeContextSlot.RuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.RuntimeContextSlot.Name.get -> string +~OpenTelemetry.Context.RuntimeContextSlot.RuntimeContextSlot(string name) -> void OpenTelemetry.Context.ThreadLocalRuntimeContextSlot -OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.ThreadLocalRuntimeContextSlot(string name) -> void -OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.get -> object -OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.set -> void +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.ThreadLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.set -> void OpenTelemetry.Metrics.IDeferredMeterProviderBuilder -OpenTelemetry.Metrics.IDeferredMeterProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder +~OpenTelemetry.Metrics.IDeferredMeterProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder OpenTelemetry.Metrics.MeterProvider OpenTelemetry.Metrics.MeterProvider.MeterProvider() -> void OpenTelemetry.Metrics.MeterProviderBuilder OpenTelemetry.Metrics.MeterProviderBuilder.MeterProviderBuilder() -> void OpenTelemetry.Trace.ActivityExtensions OpenTelemetry.Trace.IDeferredTracerProviderBuilder -OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder +~OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder OpenTelemetry.Trace.Link -OpenTelemetry.Trace.Link.Attributes.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.Link.Attributes.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.Link.Context.get -> OpenTelemetry.Trace.SpanContext OpenTelemetry.Trace.Link.Equals(OpenTelemetry.Trace.Link other) -> bool OpenTelemetry.Trace.Link.Link() -> void OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext) -> void -OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext, OpenTelemetry.Trace.SpanAttributes attributes) -> void +~OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext, OpenTelemetry.Trace.SpanAttributes attributes) -> void OpenTelemetry.Trace.SpanAttributes -OpenTelemetry.Trace.SpanAttributes.Add(string key, bool value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, bool[] values) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, double value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, double[] values) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, long value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, long[] values) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, string value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, string[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string[] values) -> void OpenTelemetry.Trace.SpanAttributes.SpanAttributes() -> void -OpenTelemetry.Trace.SpanAttributes.SpanAttributes(System.Collections.Generic.IEnumerable> attributes) -> void +~OpenTelemetry.Trace.SpanAttributes.SpanAttributes(System.Collections.Generic.IEnumerable> attributes) -> void OpenTelemetry.Trace.SpanContext OpenTelemetry.Trace.SpanContext.Equals(OpenTelemetry.Trace.SpanContext other) -> bool OpenTelemetry.Trace.SpanContext.IsRemote.get -> bool OpenTelemetry.Trace.SpanContext.IsValid.get -> bool OpenTelemetry.Trace.SpanContext.SpanContext() -> void OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityContext activityContext) -> void -OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityTraceId traceId, in System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags traceFlags, bool isRemote = false, System.Collections.Generic.IEnumerable> traceState = null) -> void +~OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityTraceId traceId, in System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags traceFlags, bool isRemote = false, System.Collections.Generic.IEnumerable> traceState = null) -> void OpenTelemetry.Trace.SpanContext.SpanId.get -> System.Diagnostics.ActivitySpanId OpenTelemetry.Trace.SpanContext.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags OpenTelemetry.Trace.SpanContext.TraceId.get -> System.Diagnostics.ActivityTraceId -OpenTelemetry.Trace.SpanContext.TraceState.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.SpanContext.TraceState.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Client = 3 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Consumer = 5 -> OpenTelemetry.Trace.SpanKind @@ -108,106 +108,106 @@ OpenTelemetry.Trace.SpanKind.Internal = 1 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Producer = 4 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Server = 2 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.Status -OpenTelemetry.Trace.Status.Description.get -> string +~OpenTelemetry.Trace.Status.Description.get -> string OpenTelemetry.Trace.Status.Equals(OpenTelemetry.Trace.Status other) -> bool OpenTelemetry.Trace.Status.Status() -> void OpenTelemetry.Trace.Status.StatusCode.get -> OpenTelemetry.Trace.StatusCode -OpenTelemetry.Trace.Status.WithDescription(string description) -> OpenTelemetry.Trace.Status +~OpenTelemetry.Trace.Status.WithDescription(string description) -> OpenTelemetry.Trace.Status OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.StatusCode.Error = 2 -> OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.StatusCode.Ok = 1 -> OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.StatusCode.Unset = 0 -> OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.TelemetrySpan.Context.get -> OpenTelemetry.Trace.SpanContext OpenTelemetry.Trace.TelemetrySpan.Dispose() -> void OpenTelemetry.Trace.TelemetrySpan.End() -> void OpenTelemetry.Trace.TelemetrySpan.End(System.DateTimeOffset endTimestamp) -> void OpenTelemetry.Trace.TelemetrySpan.IsRecording.get -> bool OpenTelemetry.Trace.TelemetrySpan.ParentSpanId.get -> System.Diagnostics.ActivitySpanId -OpenTelemetry.Trace.TelemetrySpan.RecordException(string type, string message, string stacktrace) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.RecordException(System.Exception ex) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool[] values) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double[] values) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int[] values) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.RecordException(string type, string message, string stacktrace) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.RecordException(System.Exception ex) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string[] values) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.TelemetrySpan.SetStatus(OpenTelemetry.Trace.Status value) -> void -OpenTelemetry.Trace.TelemetrySpan.UpdateName(string name) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.UpdateName(string name) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.Tracer -OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartRootSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartRootSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.TracerProvider -OpenTelemetry.Trace.TracerProvider.GetTracer(string name, string version = null) -> OpenTelemetry.Trace.Tracer +~OpenTelemetry.Trace.TracerProvider.GetTracer(string name, string version = null) -> OpenTelemetry.Trace.Tracer OpenTelemetry.Trace.TracerProvider.TracerProvider() -> void OpenTelemetry.Trace.TracerProviderBuilder OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void -override OpenTelemetry.Baggage.Equals(object obj) -> bool +~override OpenTelemetry.Baggage.Equals(object obj) -> bool override OpenTelemetry.Baggage.GetHashCode() -> int override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Get() -> T override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Set(T value) -> void -override OpenTelemetry.Context.Propagation.B3Propagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.B3Propagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.B3Propagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void -override OpenTelemetry.Context.Propagation.BaggagePropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.BaggagePropagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.BaggagePropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void -override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void -override OpenTelemetry.Context.Propagation.PropagationContext.Equals(object obj) -> bool +~override OpenTelemetry.Context.Propagation.B3Propagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.B3Propagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.B3Propagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.PropagationContext.Equals(object obj) -> bool override OpenTelemetry.Context.Propagation.PropagationContext.GetHashCode() -> int -override OpenTelemetry.Context.Propagation.TraceContextPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.TraceContextPropagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.TraceContextPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void override OpenTelemetry.Context.RemotingRuntimeContextSlot.Get() -> T override OpenTelemetry.Context.RemotingRuntimeContextSlot.Set(T value) -> void override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Dispose(bool disposing) -> void override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Get() -> T override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Set(T value) -> void -override OpenTelemetry.Trace.Link.Equals(object obj) -> bool +~override OpenTelemetry.Trace.Link.Equals(object obj) -> bool override OpenTelemetry.Trace.Link.GetHashCode() -> int -override OpenTelemetry.Trace.SpanContext.Equals(object obj) -> bool +~override OpenTelemetry.Trace.SpanContext.Equals(object obj) -> bool override OpenTelemetry.Trace.SpanContext.GetHashCode() -> int -override OpenTelemetry.Trace.Status.Equals(object obj) -> bool +~override OpenTelemetry.Trace.Status.Equals(object obj) -> bool override OpenTelemetry.Trace.Status.GetHashCode() -> int -override OpenTelemetry.Trace.Status.ToString() -> string +~override OpenTelemetry.Trace.Status.ToString() -> string static OpenTelemetry.ActivityContextExtensions.IsValid(this System.Diagnostics.ActivityContext ctx) -> bool static OpenTelemetry.Baggage.ClearBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage -static OpenTelemetry.Baggage.Create(System.Collections.Generic.Dictionary baggageItems = null) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.Create(System.Collections.Generic.Dictionary baggageItems = null) -> OpenTelemetry.Baggage static OpenTelemetry.Baggage.Current.get -> OpenTelemetry.Baggage static OpenTelemetry.Baggage.Current.set -> void -static OpenTelemetry.Baggage.GetBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.IReadOnlyDictionary -static OpenTelemetry.Baggage.GetBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> string -static OpenTelemetry.Baggage.GetEnumerator(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.Dictionary.Enumerator +~static OpenTelemetry.Baggage.GetBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.IReadOnlyDictionary +~static OpenTelemetry.Baggage.GetBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> string +~static OpenTelemetry.Baggage.GetEnumerator(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.Dictionary.Enumerator static OpenTelemetry.Baggage.operator !=(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool static OpenTelemetry.Baggage.operator ==(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool -static OpenTelemetry.Baggage.RemoveBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage -static OpenTelemetry.Baggage.SetBaggage(string name, string value, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage -static OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.RemoveBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(string name, string value, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage static OpenTelemetry.Context.Propagation.PropagationContext.operator !=(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool static OpenTelemetry.Context.Propagation.PropagationContext.operator ==(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool -static OpenTelemetry.Context.Propagation.Propagators.DefaultTextMapPropagator.get -> OpenTelemetry.Context.Propagation.TextMapPropagator -static OpenTelemetry.Context.RuntimeContext.ContextSlotType.get -> System.Type -static OpenTelemetry.Context.RuntimeContext.ContextSlotType.set -> void -static OpenTelemetry.Context.RuntimeContext.GetSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot -static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> object -static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> T -static OpenTelemetry.Context.RuntimeContext.RegisterSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot -static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, object value) -> void -static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, T value) -> void -static OpenTelemetry.Trace.ActivityExtensions.GetStatus(this System.Diagnostics.Activity activity) -> OpenTelemetry.Trace.Status -static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex) -> void -static OpenTelemetry.Trace.ActivityExtensions.SetStatus(this System.Diagnostics.Activity activity, OpenTelemetry.Trace.Status status) -> void +~static OpenTelemetry.Context.Propagation.Propagators.DefaultTextMapPropagator.get -> OpenTelemetry.Context.Propagation.TextMapPropagator +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.get -> System.Type +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.set -> void +~static OpenTelemetry.Context.RuntimeContext.GetSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> object +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> T +~static OpenTelemetry.Context.RuntimeContext.RegisterSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, object value) -> void +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, T value) -> void +~static OpenTelemetry.Trace.ActivityExtensions.GetStatus(this System.Diagnostics.Activity activity) -> OpenTelemetry.Trace.Status +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex) -> void +~static OpenTelemetry.Trace.ActivityExtensions.SetStatus(this System.Diagnostics.Activity activity, OpenTelemetry.Trace.Status status) -> void static OpenTelemetry.Trace.Link.operator !=(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool static OpenTelemetry.Trace.Link.operator ==(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool static OpenTelemetry.Trace.SpanContext.implicit operator System.Diagnostics.ActivityContext(OpenTelemetry.Trace.SpanContext spanContext) -> System.Diagnostics.ActivityContext @@ -215,9 +215,9 @@ static OpenTelemetry.Trace.SpanContext.operator !=(OpenTelemetry.Trace.SpanConte static OpenTelemetry.Trace.SpanContext.operator ==(OpenTelemetry.Trace.SpanContext spanContext1, OpenTelemetry.Trace.SpanContext spanContext2) -> bool static OpenTelemetry.Trace.Status.operator !=(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool static OpenTelemetry.Trace.Status.operator ==(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool -static OpenTelemetry.Trace.Tracer.CurrentSpan.get -> OpenTelemetry.Trace.TelemetrySpan -static OpenTelemetry.Trace.Tracer.WithSpan(OpenTelemetry.Trace.TelemetrySpan span) -> OpenTelemetry.Trace.TelemetrySpan -static OpenTelemetry.Trace.TracerProvider.Default.get -> OpenTelemetry.Trace.TracerProvider +~static OpenTelemetry.Trace.Tracer.CurrentSpan.get -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.Tracer.WithSpan(OpenTelemetry.Trace.TelemetrySpan span) -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.TracerProvider.Default.get -> OpenTelemetry.Trace.TracerProvider static readonly OpenTelemetry.Trace.Status.Error -> OpenTelemetry.Trace.Status static readonly OpenTelemetry.Trace.Status.Ok -> OpenTelemetry.Trace.Status static readonly OpenTelemetry.Trace.Status.Unset -> OpenTelemetry.Trace.Status diff --git a/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Unshipped.txt index 7883a7d9c2a..7a2d7df5780 100644 --- a/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Api/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1 +1,73 @@ -static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex, in System.Diagnostics.TagList tags) -> void +#nullable enable +abstract OpenTelemetry.Logs.Logger.EmitEvent(string! name, in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +abstract OpenTelemetry.Logs.Logger.EmitLog(in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +OpenTelemetry.InstrumentationScope +OpenTelemetry.InstrumentationScope.Attributes.get -> System.Collections.Generic.IReadOnlyDictionary? +OpenTelemetry.InstrumentationScope.Attributes.init -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope() -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope(string? name) -> void +OpenTelemetry.InstrumentationScope.Name.get -> string! +OpenTelemetry.InstrumentationScope.SchemaUrl.get -> string? +OpenTelemetry.InstrumentationScope.SchemaUrl.init -> void +OpenTelemetry.InstrumentationScope.Version.get -> string? +OpenTelemetry.InstrumentationScope.Version.init -> void +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder.Configure(System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +OpenTelemetry.Logs.Logger +OpenTelemetry.Logs.Logger.Logger(OpenTelemetry.Logs.LoggerOptions! options) -> void +OpenTelemetry.Logs.Logger.Options.get -> OpenTelemetry.Logs.LoggerOptions! +OpenTelemetry.Logs.LoggerOptions +OpenTelemetry.Logs.LoggerOptions.EventDomain.get -> string? +OpenTelemetry.Logs.LoggerOptions.EventDomain.init -> void +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.get -> bool +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.init -> void +OpenTelemetry.Logs.LoggerOptions.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope! +OpenTelemetry.Logs.LoggerOptions.LoggerOptions() -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(OpenTelemetry.InstrumentationScope! instrumentationScope) -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(string? name) -> void +OpenTelemetry.Logs.LoggerProvider +OpenTelemetry.Logs.LoggerProvider.GetLogger() -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.InstrumentationScope! instrumentationScope) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(string? name) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.LoggerProvider() -> void +OpenTelemetry.Logs.LoggerProviderBuilder +OpenTelemetry.Logs.LoggerProviderBuilder.LoggerProviderBuilder() -> void +OpenTelemetry.Logs.LogRecordAttributeList +OpenTelemetry.Logs.LogRecordAttributeList.Add(string! key, object? value) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Add(System.Collections.Generic.KeyValuePair attribute) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Count.get -> int +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Dispose() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Enumerator() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.MoveNext() -> bool +OpenTelemetry.Logs.LogRecordAttributeList.GetEnumerator() -> OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.LogRecordAttributeList() -> void +OpenTelemetry.Logs.LogRecordAttributeList.RecordException(System.Exception! exception) -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].set -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[string! key].set -> void +OpenTelemetry.Logs.LogRecordData +OpenTelemetry.Logs.LogRecordData.Body.get -> string? +OpenTelemetry.Logs.LogRecordData.Body.set -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData() -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData(System.Diagnostics.Activity? activity) -> void +OpenTelemetry.Logs.LogRecordData.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecordData.Severity.set -> void +OpenTelemetry.Logs.LogRecordData.SpanId.get -> System.Diagnostics.ActivitySpanId +OpenTelemetry.Logs.LogRecordData.SpanId.set -> void +OpenTelemetry.Logs.LogRecordData.Timestamp.get -> System.DateTime +OpenTelemetry.Logs.LogRecordData.Timestamp.set -> void +OpenTelemetry.Logs.LogRecordData.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags +OpenTelemetry.Logs.LogRecordData.TraceFlags.set -> void +OpenTelemetry.Logs.LogRecordData.TraceId.get -> System.Diagnostics.ActivityTraceId +OpenTelemetry.Logs.LogRecordData.TraceId.set -> void +OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Debug = 1 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Error = 4 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Fatal = 5 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Information = 2 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Trace = 0 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Warning = 3 -> OpenTelemetry.Logs.LogRecordSeverity +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex, in System.Diagnostics.TagList tags) -> void +virtual OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.Logs.LoggerOptions! options) -> OpenTelemetry.Logs.Logger! diff --git a/src/OpenTelemetry.Api/.publicApi/net6.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Api/.publicApi/net6.0/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..329838ddef1 --- /dev/null +++ b/src/OpenTelemetry.Api/.publicApi/net6.0/PublicAPI.Shipped.txt @@ -0,0 +1,219 @@ +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +abstract OpenTelemetry.Context.RuntimeContextSlot.Get() -> T +abstract OpenTelemetry.Context.RuntimeContextSlot.Set(T value) -> void +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +OpenTelemetry.ActivityContextExtensions +OpenTelemetry.Baggage +OpenTelemetry.Baggage.Baggage() -> void +OpenTelemetry.Baggage.ClearBaggage() -> OpenTelemetry.Baggage +OpenTelemetry.Baggage.Count.get -> int +OpenTelemetry.Baggage.Equals(OpenTelemetry.Baggage other) -> bool +~OpenTelemetry.Baggage.GetBaggage() -> System.Collections.Generic.IReadOnlyDictionary +~OpenTelemetry.Baggage.GetBaggage(string name) -> string +~OpenTelemetry.Baggage.GetEnumerator() -> System.Collections.Generic.Dictionary.Enumerator +~OpenTelemetry.Baggage.RemoveBaggage(string name) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(params System.Collections.Generic.KeyValuePair[] baggageItems) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(string name, string value) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems) -> OpenTelemetry.Baggage +OpenTelemetry.BaseProvider +OpenTelemetry.BaseProvider.~BaseProvider() -> void +OpenTelemetry.BaseProvider.BaseProvider() -> void +OpenTelemetry.BaseProvider.Dispose() -> void +OpenTelemetry.Context.AsyncLocalRuntimeContextSlot +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.AsyncLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.set -> void +OpenTelemetry.Context.IRuntimeContextSlotValueAccessor +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.get -> object +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.set -> void +OpenTelemetry.Context.Propagation.B3Propagator +OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator() -> void +OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator(bool singleHeader) -> void +OpenTelemetry.Context.Propagation.BaggagePropagator +OpenTelemetry.Context.Propagation.BaggagePropagator.BaggagePropagator() -> void +OpenTelemetry.Context.Propagation.CompositeTextMapPropagator +~OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.CompositeTextMapPropagator(System.Collections.Generic.IEnumerable propagators) -> void +OpenTelemetry.Context.Propagation.PropagationContext +OpenTelemetry.Context.Propagation.PropagationContext.ActivityContext.get -> System.Diagnostics.ActivityContext +OpenTelemetry.Context.Propagation.PropagationContext.Baggage.get -> OpenTelemetry.Baggage +OpenTelemetry.Context.Propagation.PropagationContext.Equals(OpenTelemetry.Context.Propagation.PropagationContext value) -> bool +OpenTelemetry.Context.Propagation.PropagationContext.PropagationContext() -> void +OpenTelemetry.Context.Propagation.PropagationContext.PropagationContext(System.Diagnostics.ActivityContext activityContext, OpenTelemetry.Baggage baggage) -> void +OpenTelemetry.Context.Propagation.Propagators +OpenTelemetry.Context.Propagation.TextMapPropagator +OpenTelemetry.Context.Propagation.TextMapPropagator.TextMapPropagator() -> void +OpenTelemetry.Context.Propagation.TraceContextPropagator +OpenTelemetry.Context.Propagation.TraceContextPropagator.TraceContextPropagator() -> void +OpenTelemetry.Context.RuntimeContext +OpenTelemetry.Context.RuntimeContextSlot +OpenTelemetry.Context.RuntimeContextSlot.Dispose() -> void +~OpenTelemetry.Context.RuntimeContextSlot.Name.get -> string +~OpenTelemetry.Context.RuntimeContextSlot.RuntimeContextSlot(string name) -> void +OpenTelemetry.Context.ThreadLocalRuntimeContextSlot +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.ThreadLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.set -> void +OpenTelemetry.Metrics.IDeferredMeterProviderBuilder +~OpenTelemetry.Metrics.IDeferredMeterProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder +OpenTelemetry.Metrics.MeterProvider +OpenTelemetry.Metrics.MeterProvider.MeterProvider() -> void +OpenTelemetry.Metrics.MeterProviderBuilder +OpenTelemetry.Metrics.MeterProviderBuilder.MeterProviderBuilder() -> void +OpenTelemetry.Trace.ActivityExtensions +OpenTelemetry.Trace.IDeferredTracerProviderBuilder +~OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder +OpenTelemetry.Trace.Link +~OpenTelemetry.Trace.Link.Attributes.get -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Trace.Link.Context.get -> OpenTelemetry.Trace.SpanContext +OpenTelemetry.Trace.Link.Equals(OpenTelemetry.Trace.Link other) -> bool +OpenTelemetry.Trace.Link.Link() -> void +OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext) -> void +~OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext, OpenTelemetry.Trace.SpanAttributes attributes) -> void +OpenTelemetry.Trace.SpanAttributes +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string[] values) -> void +OpenTelemetry.Trace.SpanAttributes.SpanAttributes() -> void +~OpenTelemetry.Trace.SpanAttributes.SpanAttributes(System.Collections.Generic.IEnumerable> attributes) -> void +OpenTelemetry.Trace.SpanContext +OpenTelemetry.Trace.SpanContext.Equals(OpenTelemetry.Trace.SpanContext other) -> bool +OpenTelemetry.Trace.SpanContext.IsRemote.get -> bool +OpenTelemetry.Trace.SpanContext.IsValid.get -> bool +OpenTelemetry.Trace.SpanContext.SpanContext() -> void +OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityContext activityContext) -> void +~OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityTraceId traceId, in System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags traceFlags, bool isRemote = false, System.Collections.Generic.IEnumerable> traceState = null) -> void +OpenTelemetry.Trace.SpanContext.SpanId.get -> System.Diagnostics.ActivitySpanId +OpenTelemetry.Trace.SpanContext.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags +OpenTelemetry.Trace.SpanContext.TraceId.get -> System.Diagnostics.ActivityTraceId +~OpenTelemetry.Trace.SpanContext.TraceState.get -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Client = 3 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Consumer = 5 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Internal = 1 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Producer = 4 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Server = 2 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.Status +~OpenTelemetry.Trace.Status.Description.get -> string +OpenTelemetry.Trace.Status.Equals(OpenTelemetry.Trace.Status other) -> bool +OpenTelemetry.Trace.Status.Status() -> void +OpenTelemetry.Trace.Status.StatusCode.get -> OpenTelemetry.Trace.StatusCode +~OpenTelemetry.Trace.Status.WithDescription(string description) -> OpenTelemetry.Trace.Status +OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.StatusCode.Error = 2 -> OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.StatusCode.Ok = 1 -> OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.StatusCode.Unset = 0 -> OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.TelemetrySpan.Context.get -> OpenTelemetry.Trace.SpanContext +OpenTelemetry.Trace.TelemetrySpan.Dispose() -> void +OpenTelemetry.Trace.TelemetrySpan.End() -> void +OpenTelemetry.Trace.TelemetrySpan.End(System.DateTimeOffset endTimestamp) -> void +OpenTelemetry.Trace.TelemetrySpan.IsRecording.get -> bool +OpenTelemetry.Trace.TelemetrySpan.ParentSpanId.get -> System.Diagnostics.ActivitySpanId +~OpenTelemetry.Trace.TelemetrySpan.RecordException(string type, string message, string stacktrace) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.RecordException(System.Exception ex) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string[] values) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.TelemetrySpan.SetStatus(OpenTelemetry.Trace.Status value) -> void +~OpenTelemetry.Trace.TelemetrySpan.UpdateName(string name) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.Tracer +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartRootSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.TracerProvider +~OpenTelemetry.Trace.TracerProvider.GetTracer(string name, string version = null) -> OpenTelemetry.Trace.Tracer +OpenTelemetry.Trace.TracerProvider.TracerProvider() -> void +OpenTelemetry.Trace.TracerProviderBuilder +OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void +~override OpenTelemetry.Baggage.Equals(object obj) -> bool +override OpenTelemetry.Baggage.GetHashCode() -> int +override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Get() -> T +override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Set(T value) -> void +~override OpenTelemetry.Context.Propagation.B3Propagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.B3Propagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.B3Propagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.PropagationContext.Equals(object obj) -> bool +override OpenTelemetry.Context.Propagation.PropagationContext.GetHashCode() -> int +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Dispose(bool disposing) -> void +override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Get() -> T +override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Set(T value) -> void +~override OpenTelemetry.Trace.Link.Equals(object obj) -> bool +override OpenTelemetry.Trace.Link.GetHashCode() -> int +~override OpenTelemetry.Trace.SpanContext.Equals(object obj) -> bool +override OpenTelemetry.Trace.SpanContext.GetHashCode() -> int +~override OpenTelemetry.Trace.Status.Equals(object obj) -> bool +override OpenTelemetry.Trace.Status.GetHashCode() -> int +~override OpenTelemetry.Trace.Status.ToString() -> string +static OpenTelemetry.ActivityContextExtensions.IsValid(this System.Diagnostics.ActivityContext ctx) -> bool +static OpenTelemetry.Baggage.ClearBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.Create(System.Collections.Generic.Dictionary baggageItems = null) -> OpenTelemetry.Baggage +static OpenTelemetry.Baggage.Current.get -> OpenTelemetry.Baggage +static OpenTelemetry.Baggage.Current.set -> void +~static OpenTelemetry.Baggage.GetBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.IReadOnlyDictionary +~static OpenTelemetry.Baggage.GetBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> string +~static OpenTelemetry.Baggage.GetEnumerator(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.Dictionary.Enumerator +static OpenTelemetry.Baggage.operator !=(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool +static OpenTelemetry.Baggage.operator ==(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool +~static OpenTelemetry.Baggage.RemoveBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(string name, string value, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +static OpenTelemetry.Context.Propagation.PropagationContext.operator !=(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool +static OpenTelemetry.Context.Propagation.PropagationContext.operator ==(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool +~static OpenTelemetry.Context.Propagation.Propagators.DefaultTextMapPropagator.get -> OpenTelemetry.Context.Propagation.TextMapPropagator +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.get -> System.Type +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.set -> void +~static OpenTelemetry.Context.RuntimeContext.GetSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> object +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> T +~static OpenTelemetry.Context.RuntimeContext.RegisterSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, object value) -> void +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, T value) -> void +~static OpenTelemetry.Trace.ActivityExtensions.GetStatus(this System.Diagnostics.Activity activity) -> OpenTelemetry.Trace.Status +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex) -> void +~static OpenTelemetry.Trace.ActivityExtensions.SetStatus(this System.Diagnostics.Activity activity, OpenTelemetry.Trace.Status status) -> void +static OpenTelemetry.Trace.Link.operator !=(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool +static OpenTelemetry.Trace.Link.operator ==(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool +static OpenTelemetry.Trace.SpanContext.implicit operator System.Diagnostics.ActivityContext(OpenTelemetry.Trace.SpanContext spanContext) -> System.Diagnostics.ActivityContext +static OpenTelemetry.Trace.SpanContext.operator !=(OpenTelemetry.Trace.SpanContext spanContext1, OpenTelemetry.Trace.SpanContext spanContext2) -> bool +static OpenTelemetry.Trace.SpanContext.operator ==(OpenTelemetry.Trace.SpanContext spanContext1, OpenTelemetry.Trace.SpanContext spanContext2) -> bool +static OpenTelemetry.Trace.Status.operator !=(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool +static OpenTelemetry.Trace.Status.operator ==(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool +~static OpenTelemetry.Trace.Tracer.CurrentSpan.get -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.Tracer.WithSpan(OpenTelemetry.Trace.TelemetrySpan span) -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.TracerProvider.Default.get -> OpenTelemetry.Trace.TracerProvider +static readonly OpenTelemetry.Trace.Status.Error -> OpenTelemetry.Trace.Status +static readonly OpenTelemetry.Trace.Status.Ok -> OpenTelemetry.Trace.Status +static readonly OpenTelemetry.Trace.Status.Unset -> OpenTelemetry.Trace.Status +virtual OpenTelemetry.BaseProvider.Dispose(bool disposing) -> void +virtual OpenTelemetry.Context.RuntimeContextSlot.Dispose(bool disposing) -> void diff --git a/src/OpenTelemetry.Api/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Api/.publicApi/net6.0/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..7a2d7df5780 --- /dev/null +++ b/src/OpenTelemetry.Api/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -0,0 +1,73 @@ +#nullable enable +abstract OpenTelemetry.Logs.Logger.EmitEvent(string! name, in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +abstract OpenTelemetry.Logs.Logger.EmitLog(in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +OpenTelemetry.InstrumentationScope +OpenTelemetry.InstrumentationScope.Attributes.get -> System.Collections.Generic.IReadOnlyDictionary? +OpenTelemetry.InstrumentationScope.Attributes.init -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope() -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope(string? name) -> void +OpenTelemetry.InstrumentationScope.Name.get -> string! +OpenTelemetry.InstrumentationScope.SchemaUrl.get -> string? +OpenTelemetry.InstrumentationScope.SchemaUrl.init -> void +OpenTelemetry.InstrumentationScope.Version.get -> string? +OpenTelemetry.InstrumentationScope.Version.init -> void +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder.Configure(System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +OpenTelemetry.Logs.Logger +OpenTelemetry.Logs.Logger.Logger(OpenTelemetry.Logs.LoggerOptions! options) -> void +OpenTelemetry.Logs.Logger.Options.get -> OpenTelemetry.Logs.LoggerOptions! +OpenTelemetry.Logs.LoggerOptions +OpenTelemetry.Logs.LoggerOptions.EventDomain.get -> string? +OpenTelemetry.Logs.LoggerOptions.EventDomain.init -> void +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.get -> bool +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.init -> void +OpenTelemetry.Logs.LoggerOptions.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope! +OpenTelemetry.Logs.LoggerOptions.LoggerOptions() -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(OpenTelemetry.InstrumentationScope! instrumentationScope) -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(string? name) -> void +OpenTelemetry.Logs.LoggerProvider +OpenTelemetry.Logs.LoggerProvider.GetLogger() -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.InstrumentationScope! instrumentationScope) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(string? name) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.LoggerProvider() -> void +OpenTelemetry.Logs.LoggerProviderBuilder +OpenTelemetry.Logs.LoggerProviderBuilder.LoggerProviderBuilder() -> void +OpenTelemetry.Logs.LogRecordAttributeList +OpenTelemetry.Logs.LogRecordAttributeList.Add(string! key, object? value) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Add(System.Collections.Generic.KeyValuePair attribute) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Count.get -> int +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Dispose() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Enumerator() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.MoveNext() -> bool +OpenTelemetry.Logs.LogRecordAttributeList.GetEnumerator() -> OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.LogRecordAttributeList() -> void +OpenTelemetry.Logs.LogRecordAttributeList.RecordException(System.Exception! exception) -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].set -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[string! key].set -> void +OpenTelemetry.Logs.LogRecordData +OpenTelemetry.Logs.LogRecordData.Body.get -> string? +OpenTelemetry.Logs.LogRecordData.Body.set -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData() -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData(System.Diagnostics.Activity? activity) -> void +OpenTelemetry.Logs.LogRecordData.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecordData.Severity.set -> void +OpenTelemetry.Logs.LogRecordData.SpanId.get -> System.Diagnostics.ActivitySpanId +OpenTelemetry.Logs.LogRecordData.SpanId.set -> void +OpenTelemetry.Logs.LogRecordData.Timestamp.get -> System.DateTime +OpenTelemetry.Logs.LogRecordData.Timestamp.set -> void +OpenTelemetry.Logs.LogRecordData.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags +OpenTelemetry.Logs.LogRecordData.TraceFlags.set -> void +OpenTelemetry.Logs.LogRecordData.TraceId.get -> System.Diagnostics.ActivityTraceId +OpenTelemetry.Logs.LogRecordData.TraceId.set -> void +OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Debug = 1 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Error = 4 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Fatal = 5 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Information = 2 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Trace = 0 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Warning = 3 -> OpenTelemetry.Logs.LogRecordSeverity +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex, in System.Diagnostics.TagList tags) -> void +virtual OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.Logs.LoggerOptions! options) -> OpenTelemetry.Logs.Logger! diff --git a/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Shipped.txt index 7f06c3364e1..329838ddef1 100644 --- a/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Shipped.txt @@ -1,44 +1,44 @@ -abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Fields.get -> System.Collections.Generic.ISet -abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void abstract OpenTelemetry.Context.RuntimeContextSlot.Get() -> T abstract OpenTelemetry.Context.RuntimeContextSlot.Set(T value) -> void -abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder -abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder -abstract OpenTelemetry.Trace.TracerProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder -abstract OpenTelemetry.Trace.TracerProviderBuilder.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder -abstract OpenTelemetry.Trace.TracerProviderBuilder.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder OpenTelemetry.ActivityContextExtensions OpenTelemetry.Baggage OpenTelemetry.Baggage.Baggage() -> void OpenTelemetry.Baggage.ClearBaggage() -> OpenTelemetry.Baggage OpenTelemetry.Baggage.Count.get -> int OpenTelemetry.Baggage.Equals(OpenTelemetry.Baggage other) -> bool -OpenTelemetry.Baggage.GetBaggage() -> System.Collections.Generic.IReadOnlyDictionary -OpenTelemetry.Baggage.GetBaggage(string name) -> string -OpenTelemetry.Baggage.GetEnumerator() -> System.Collections.Generic.Dictionary.Enumerator -OpenTelemetry.Baggage.RemoveBaggage(string name) -> OpenTelemetry.Baggage -OpenTelemetry.Baggage.SetBaggage(params System.Collections.Generic.KeyValuePair[] baggageItems) -> OpenTelemetry.Baggage -OpenTelemetry.Baggage.SetBaggage(string name, string value) -> OpenTelemetry.Baggage -OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.GetBaggage() -> System.Collections.Generic.IReadOnlyDictionary +~OpenTelemetry.Baggage.GetBaggage(string name) -> string +~OpenTelemetry.Baggage.GetEnumerator() -> System.Collections.Generic.Dictionary.Enumerator +~OpenTelemetry.Baggage.RemoveBaggage(string name) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(params System.Collections.Generic.KeyValuePair[] baggageItems) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(string name, string value) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems) -> OpenTelemetry.Baggage OpenTelemetry.BaseProvider OpenTelemetry.BaseProvider.~BaseProvider() -> void OpenTelemetry.BaseProvider.BaseProvider() -> void OpenTelemetry.BaseProvider.Dispose() -> void OpenTelemetry.Context.AsyncLocalRuntimeContextSlot -OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.AsyncLocalRuntimeContextSlot(string name) -> void -OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.get -> object -OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.set -> void +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.AsyncLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.set -> void OpenTelemetry.Context.IRuntimeContextSlotValueAccessor -OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.get -> object -OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.set -> void +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.get -> object +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.set -> void OpenTelemetry.Context.Propagation.B3Propagator OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator() -> void OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator(bool singleHeader) -> void OpenTelemetry.Context.Propagation.BaggagePropagator OpenTelemetry.Context.Propagation.BaggagePropagator.BaggagePropagator() -> void OpenTelemetry.Context.Propagation.CompositeTextMapPropagator -OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.CompositeTextMapPropagator(System.Collections.Generic.IEnumerable propagators) -> void +~OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.CompositeTextMapPropagator(System.Collections.Generic.IEnumerable propagators) -> void OpenTelemetry.Context.Propagation.PropagationContext OpenTelemetry.Context.Propagation.PropagationContext.ActivityContext.get -> System.Diagnostics.ActivityContext OpenTelemetry.Context.Propagation.PropagationContext.Baggage.get -> OpenTelemetry.Baggage @@ -53,50 +53,50 @@ OpenTelemetry.Context.Propagation.TraceContextPropagator.TraceContextPropagator( OpenTelemetry.Context.RuntimeContext OpenTelemetry.Context.RuntimeContextSlot OpenTelemetry.Context.RuntimeContextSlot.Dispose() -> void -OpenTelemetry.Context.RuntimeContextSlot.Name.get -> string -OpenTelemetry.Context.RuntimeContextSlot.RuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.RuntimeContextSlot.Name.get -> string +~OpenTelemetry.Context.RuntimeContextSlot.RuntimeContextSlot(string name) -> void OpenTelemetry.Context.ThreadLocalRuntimeContextSlot -OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.ThreadLocalRuntimeContextSlot(string name) -> void -OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.get -> object -OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.set -> void +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.ThreadLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.set -> void OpenTelemetry.Metrics.IDeferredMeterProviderBuilder -OpenTelemetry.Metrics.IDeferredMeterProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder +~OpenTelemetry.Metrics.IDeferredMeterProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder OpenTelemetry.Metrics.MeterProvider OpenTelemetry.Metrics.MeterProvider.MeterProvider() -> void OpenTelemetry.Metrics.MeterProviderBuilder OpenTelemetry.Metrics.MeterProviderBuilder.MeterProviderBuilder() -> void OpenTelemetry.Trace.ActivityExtensions OpenTelemetry.Trace.IDeferredTracerProviderBuilder -OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder +~OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder OpenTelemetry.Trace.Link -OpenTelemetry.Trace.Link.Attributes.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.Link.Attributes.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.Link.Context.get -> OpenTelemetry.Trace.SpanContext OpenTelemetry.Trace.Link.Equals(OpenTelemetry.Trace.Link other) -> bool OpenTelemetry.Trace.Link.Link() -> void OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext) -> void -OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext, OpenTelemetry.Trace.SpanAttributes attributes) -> void +~OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext, OpenTelemetry.Trace.SpanAttributes attributes) -> void OpenTelemetry.Trace.SpanAttributes -OpenTelemetry.Trace.SpanAttributes.Add(string key, bool value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, bool[] values) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, double value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, double[] values) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, long value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, long[] values) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, string value) -> void -OpenTelemetry.Trace.SpanAttributes.Add(string key, string[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string[] values) -> void OpenTelemetry.Trace.SpanAttributes.SpanAttributes() -> void -OpenTelemetry.Trace.SpanAttributes.SpanAttributes(System.Collections.Generic.IEnumerable> attributes) -> void +~OpenTelemetry.Trace.SpanAttributes.SpanAttributes(System.Collections.Generic.IEnumerable> attributes) -> void OpenTelemetry.Trace.SpanContext OpenTelemetry.Trace.SpanContext.Equals(OpenTelemetry.Trace.SpanContext other) -> bool OpenTelemetry.Trace.SpanContext.IsRemote.get -> bool OpenTelemetry.Trace.SpanContext.IsValid.get -> bool OpenTelemetry.Trace.SpanContext.SpanContext() -> void OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityContext activityContext) -> void -OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityTraceId traceId, in System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags traceFlags, bool isRemote = false, System.Collections.Generic.IEnumerable> traceState = null) -> void +~OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityTraceId traceId, in System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags traceFlags, bool isRemote = false, System.Collections.Generic.IEnumerable> traceState = null) -> void OpenTelemetry.Trace.SpanContext.SpanId.get -> System.Diagnostics.ActivitySpanId OpenTelemetry.Trace.SpanContext.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags OpenTelemetry.Trace.SpanContext.TraceId.get -> System.Diagnostics.ActivityTraceId -OpenTelemetry.Trace.SpanContext.TraceState.get -> System.Collections.Generic.IEnumerable> +~OpenTelemetry.Trace.SpanContext.TraceState.get -> System.Collections.Generic.IEnumerable> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Client = 3 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Consumer = 5 -> OpenTelemetry.Trace.SpanKind @@ -104,104 +104,104 @@ OpenTelemetry.Trace.SpanKind.Internal = 1 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Producer = 4 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.SpanKind.Server = 2 -> OpenTelemetry.Trace.SpanKind OpenTelemetry.Trace.Status -OpenTelemetry.Trace.Status.Description.get -> string +~OpenTelemetry.Trace.Status.Description.get -> string OpenTelemetry.Trace.Status.Equals(OpenTelemetry.Trace.Status other) -> bool OpenTelemetry.Trace.Status.Status() -> void OpenTelemetry.Trace.Status.StatusCode.get -> OpenTelemetry.Trace.StatusCode -OpenTelemetry.Trace.Status.WithDescription(string description) -> OpenTelemetry.Trace.Status +~OpenTelemetry.Trace.Status.WithDescription(string description) -> OpenTelemetry.Trace.Status OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.StatusCode.Error = 2 -> OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.StatusCode.Ok = 1 -> OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.StatusCode.Unset = 0 -> OpenTelemetry.Trace.StatusCode OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.TelemetrySpan.Context.get -> OpenTelemetry.Trace.SpanContext OpenTelemetry.Trace.TelemetrySpan.Dispose() -> void OpenTelemetry.Trace.TelemetrySpan.End() -> void OpenTelemetry.Trace.TelemetrySpan.End(System.DateTimeOffset endTimestamp) -> void OpenTelemetry.Trace.TelemetrySpan.IsRecording.get -> bool OpenTelemetry.Trace.TelemetrySpan.ParentSpanId.get -> System.Diagnostics.ActivitySpanId -OpenTelemetry.Trace.TelemetrySpan.RecordException(string type, string message, string stacktrace) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.RecordException(System.Exception ex) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool[] values) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double[] values) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int[] values) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string value) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.RecordException(string type, string message, string stacktrace) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.RecordException(System.Exception ex) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string[] values) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.TelemetrySpan.SetStatus(OpenTelemetry.Trace.Status value) -> void -OpenTelemetry.Trace.TelemetrySpan.UpdateName(string name) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.UpdateName(string name) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.Tracer -OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartRootSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan -OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartRootSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan OpenTelemetry.Trace.TracerProvider -OpenTelemetry.Trace.TracerProvider.GetTracer(string name, string version = null) -> OpenTelemetry.Trace.Tracer +~OpenTelemetry.Trace.TracerProvider.GetTracer(string name, string version = null) -> OpenTelemetry.Trace.Tracer OpenTelemetry.Trace.TracerProvider.TracerProvider() -> void OpenTelemetry.Trace.TracerProviderBuilder OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void -override OpenTelemetry.Baggage.Equals(object obj) -> bool +~override OpenTelemetry.Baggage.Equals(object obj) -> bool override OpenTelemetry.Baggage.GetHashCode() -> int override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Get() -> T override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Set(T value) -> void -override OpenTelemetry.Context.Propagation.B3Propagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.B3Propagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.B3Propagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void -override OpenTelemetry.Context.Propagation.BaggagePropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.BaggagePropagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.BaggagePropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void -override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void -override OpenTelemetry.Context.Propagation.PropagationContext.Equals(object obj) -> bool +~override OpenTelemetry.Context.Propagation.B3Propagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.B3Propagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.B3Propagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.PropagationContext.Equals(object obj) -> bool override OpenTelemetry.Context.Propagation.PropagationContext.GetHashCode() -> int -override OpenTelemetry.Context.Propagation.TraceContextPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext -override OpenTelemetry.Context.Propagation.TraceContextPropagator.Fields.get -> System.Collections.Generic.ISet -override OpenTelemetry.Context.Propagation.TraceContextPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Dispose(bool disposing) -> void override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Get() -> T override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Set(T value) -> void -override OpenTelemetry.Trace.Link.Equals(object obj) -> bool +~override OpenTelemetry.Trace.Link.Equals(object obj) -> bool override OpenTelemetry.Trace.Link.GetHashCode() -> int -override OpenTelemetry.Trace.SpanContext.Equals(object obj) -> bool +~override OpenTelemetry.Trace.SpanContext.Equals(object obj) -> bool override OpenTelemetry.Trace.SpanContext.GetHashCode() -> int -override OpenTelemetry.Trace.Status.Equals(object obj) -> bool +~override OpenTelemetry.Trace.Status.Equals(object obj) -> bool override OpenTelemetry.Trace.Status.GetHashCode() -> int -override OpenTelemetry.Trace.Status.ToString() -> string +~override OpenTelemetry.Trace.Status.ToString() -> string static OpenTelemetry.ActivityContextExtensions.IsValid(this System.Diagnostics.ActivityContext ctx) -> bool static OpenTelemetry.Baggage.ClearBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage -static OpenTelemetry.Baggage.Create(System.Collections.Generic.Dictionary baggageItems = null) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.Create(System.Collections.Generic.Dictionary baggageItems = null) -> OpenTelemetry.Baggage static OpenTelemetry.Baggage.Current.get -> OpenTelemetry.Baggage static OpenTelemetry.Baggage.Current.set -> void -static OpenTelemetry.Baggage.GetBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.IReadOnlyDictionary -static OpenTelemetry.Baggage.GetBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> string -static OpenTelemetry.Baggage.GetEnumerator(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.Dictionary.Enumerator +~static OpenTelemetry.Baggage.GetBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.IReadOnlyDictionary +~static OpenTelemetry.Baggage.GetBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> string +~static OpenTelemetry.Baggage.GetEnumerator(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.Dictionary.Enumerator static OpenTelemetry.Baggage.operator !=(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool static OpenTelemetry.Baggage.operator ==(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool -static OpenTelemetry.Baggage.RemoveBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage -static OpenTelemetry.Baggage.SetBaggage(string name, string value, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage -static OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.RemoveBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(string name, string value, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage static OpenTelemetry.Context.Propagation.PropagationContext.operator !=(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool static OpenTelemetry.Context.Propagation.PropagationContext.operator ==(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool -static OpenTelemetry.Context.Propagation.Propagators.DefaultTextMapPropagator.get -> OpenTelemetry.Context.Propagation.TextMapPropagator -static OpenTelemetry.Context.RuntimeContext.ContextSlotType.get -> System.Type -static OpenTelemetry.Context.RuntimeContext.ContextSlotType.set -> void -static OpenTelemetry.Context.RuntimeContext.GetSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot -static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> object -static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> T -static OpenTelemetry.Context.RuntimeContext.RegisterSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot -static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, object value) -> void -static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, T value) -> void -static OpenTelemetry.Trace.ActivityExtensions.GetStatus(this System.Diagnostics.Activity activity) -> OpenTelemetry.Trace.Status -static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex) -> void -static OpenTelemetry.Trace.ActivityExtensions.SetStatus(this System.Diagnostics.Activity activity, OpenTelemetry.Trace.Status status) -> void +~static OpenTelemetry.Context.Propagation.Propagators.DefaultTextMapPropagator.get -> OpenTelemetry.Context.Propagation.TextMapPropagator +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.get -> System.Type +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.set -> void +~static OpenTelemetry.Context.RuntimeContext.GetSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> object +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> T +~static OpenTelemetry.Context.RuntimeContext.RegisterSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, object value) -> void +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, T value) -> void +~static OpenTelemetry.Trace.ActivityExtensions.GetStatus(this System.Diagnostics.Activity activity) -> OpenTelemetry.Trace.Status +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex) -> void +~static OpenTelemetry.Trace.ActivityExtensions.SetStatus(this System.Diagnostics.Activity activity, OpenTelemetry.Trace.Status status) -> void static OpenTelemetry.Trace.Link.operator !=(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool static OpenTelemetry.Trace.Link.operator ==(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool static OpenTelemetry.Trace.SpanContext.implicit operator System.Diagnostics.ActivityContext(OpenTelemetry.Trace.SpanContext spanContext) -> System.Diagnostics.ActivityContext @@ -209,9 +209,9 @@ static OpenTelemetry.Trace.SpanContext.operator !=(OpenTelemetry.Trace.SpanConte static OpenTelemetry.Trace.SpanContext.operator ==(OpenTelemetry.Trace.SpanContext spanContext1, OpenTelemetry.Trace.SpanContext spanContext2) -> bool static OpenTelemetry.Trace.Status.operator !=(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool static OpenTelemetry.Trace.Status.operator ==(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool -static OpenTelemetry.Trace.Tracer.CurrentSpan.get -> OpenTelemetry.Trace.TelemetrySpan -static OpenTelemetry.Trace.Tracer.WithSpan(OpenTelemetry.Trace.TelemetrySpan span) -> OpenTelemetry.Trace.TelemetrySpan -static OpenTelemetry.Trace.TracerProvider.Default.get -> OpenTelemetry.Trace.TracerProvider +~static OpenTelemetry.Trace.Tracer.CurrentSpan.get -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.Tracer.WithSpan(OpenTelemetry.Trace.TelemetrySpan span) -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.TracerProvider.Default.get -> OpenTelemetry.Trace.TracerProvider static readonly OpenTelemetry.Trace.Status.Error -> OpenTelemetry.Trace.Status static readonly OpenTelemetry.Trace.Status.Ok -> OpenTelemetry.Trace.Status static readonly OpenTelemetry.Trace.Status.Unset -> OpenTelemetry.Trace.Status diff --git a/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 7883a7d9c2a..7a2d7df5780 100644 --- a/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Api/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1 +1,73 @@ -static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex, in System.Diagnostics.TagList tags) -> void +#nullable enable +abstract OpenTelemetry.Logs.Logger.EmitEvent(string! name, in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +abstract OpenTelemetry.Logs.Logger.EmitLog(in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +OpenTelemetry.InstrumentationScope +OpenTelemetry.InstrumentationScope.Attributes.get -> System.Collections.Generic.IReadOnlyDictionary? +OpenTelemetry.InstrumentationScope.Attributes.init -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope() -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope(string? name) -> void +OpenTelemetry.InstrumentationScope.Name.get -> string! +OpenTelemetry.InstrumentationScope.SchemaUrl.get -> string? +OpenTelemetry.InstrumentationScope.SchemaUrl.init -> void +OpenTelemetry.InstrumentationScope.Version.get -> string? +OpenTelemetry.InstrumentationScope.Version.init -> void +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder.Configure(System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +OpenTelemetry.Logs.Logger +OpenTelemetry.Logs.Logger.Logger(OpenTelemetry.Logs.LoggerOptions! options) -> void +OpenTelemetry.Logs.Logger.Options.get -> OpenTelemetry.Logs.LoggerOptions! +OpenTelemetry.Logs.LoggerOptions +OpenTelemetry.Logs.LoggerOptions.EventDomain.get -> string? +OpenTelemetry.Logs.LoggerOptions.EventDomain.init -> void +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.get -> bool +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.init -> void +OpenTelemetry.Logs.LoggerOptions.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope! +OpenTelemetry.Logs.LoggerOptions.LoggerOptions() -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(OpenTelemetry.InstrumentationScope! instrumentationScope) -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(string? name) -> void +OpenTelemetry.Logs.LoggerProvider +OpenTelemetry.Logs.LoggerProvider.GetLogger() -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.InstrumentationScope! instrumentationScope) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(string? name) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.LoggerProvider() -> void +OpenTelemetry.Logs.LoggerProviderBuilder +OpenTelemetry.Logs.LoggerProviderBuilder.LoggerProviderBuilder() -> void +OpenTelemetry.Logs.LogRecordAttributeList +OpenTelemetry.Logs.LogRecordAttributeList.Add(string! key, object? value) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Add(System.Collections.Generic.KeyValuePair attribute) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Count.get -> int +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Dispose() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Enumerator() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.MoveNext() -> bool +OpenTelemetry.Logs.LogRecordAttributeList.GetEnumerator() -> OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.LogRecordAttributeList() -> void +OpenTelemetry.Logs.LogRecordAttributeList.RecordException(System.Exception! exception) -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].set -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[string! key].set -> void +OpenTelemetry.Logs.LogRecordData +OpenTelemetry.Logs.LogRecordData.Body.get -> string? +OpenTelemetry.Logs.LogRecordData.Body.set -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData() -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData(System.Diagnostics.Activity? activity) -> void +OpenTelemetry.Logs.LogRecordData.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecordData.Severity.set -> void +OpenTelemetry.Logs.LogRecordData.SpanId.get -> System.Diagnostics.ActivitySpanId +OpenTelemetry.Logs.LogRecordData.SpanId.set -> void +OpenTelemetry.Logs.LogRecordData.Timestamp.get -> System.DateTime +OpenTelemetry.Logs.LogRecordData.Timestamp.set -> void +OpenTelemetry.Logs.LogRecordData.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags +OpenTelemetry.Logs.LogRecordData.TraceFlags.set -> void +OpenTelemetry.Logs.LogRecordData.TraceId.get -> System.Diagnostics.ActivityTraceId +OpenTelemetry.Logs.LogRecordData.TraceId.set -> void +OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Debug = 1 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Error = 4 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Fatal = 5 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Information = 2 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Trace = 0 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Warning = 3 -> OpenTelemetry.Logs.LogRecordSeverity +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex, in System.Diagnostics.TagList tags) -> void +virtual OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.Logs.LoggerOptions! options) -> OpenTelemetry.Logs.Logger! diff --git a/src/OpenTelemetry.Api/.publicApi/netstandard2.1/PublicAPI.Shipped.txt b/src/OpenTelemetry.Api/.publicApi/netstandard2.1/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..329838ddef1 --- /dev/null +++ b/src/OpenTelemetry.Api/.publicApi/netstandard2.1/PublicAPI.Shipped.txt @@ -0,0 +1,219 @@ +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~abstract OpenTelemetry.Context.Propagation.TextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +abstract OpenTelemetry.Context.RuntimeContextSlot.Get() -> T +abstract OpenTelemetry.Context.RuntimeContextSlot.Set(T value) -> void +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Metrics.MeterProviderBuilder.AddMeter(params string[] names) -> OpenTelemetry.Metrics.MeterProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddInstrumentation(System.Func instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddLegacySource(string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder +~abstract OpenTelemetry.Trace.TracerProviderBuilder.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder +OpenTelemetry.ActivityContextExtensions +OpenTelemetry.Baggage +OpenTelemetry.Baggage.Baggage() -> void +OpenTelemetry.Baggage.ClearBaggage() -> OpenTelemetry.Baggage +OpenTelemetry.Baggage.Count.get -> int +OpenTelemetry.Baggage.Equals(OpenTelemetry.Baggage other) -> bool +~OpenTelemetry.Baggage.GetBaggage() -> System.Collections.Generic.IReadOnlyDictionary +~OpenTelemetry.Baggage.GetBaggage(string name) -> string +~OpenTelemetry.Baggage.GetEnumerator() -> System.Collections.Generic.Dictionary.Enumerator +~OpenTelemetry.Baggage.RemoveBaggage(string name) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(params System.Collections.Generic.KeyValuePair[] baggageItems) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(string name, string value) -> OpenTelemetry.Baggage +~OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems) -> OpenTelemetry.Baggage +OpenTelemetry.BaseProvider +OpenTelemetry.BaseProvider.~BaseProvider() -> void +OpenTelemetry.BaseProvider.BaseProvider() -> void +OpenTelemetry.BaseProvider.Dispose() -> void +OpenTelemetry.Context.AsyncLocalRuntimeContextSlot +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.AsyncLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Value.set -> void +OpenTelemetry.Context.IRuntimeContextSlotValueAccessor +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.get -> object +~OpenTelemetry.Context.IRuntimeContextSlotValueAccessor.Value.set -> void +OpenTelemetry.Context.Propagation.B3Propagator +OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator() -> void +OpenTelemetry.Context.Propagation.B3Propagator.B3Propagator(bool singleHeader) -> void +OpenTelemetry.Context.Propagation.BaggagePropagator +OpenTelemetry.Context.Propagation.BaggagePropagator.BaggagePropagator() -> void +OpenTelemetry.Context.Propagation.CompositeTextMapPropagator +~OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.CompositeTextMapPropagator(System.Collections.Generic.IEnumerable propagators) -> void +OpenTelemetry.Context.Propagation.PropagationContext +OpenTelemetry.Context.Propagation.PropagationContext.ActivityContext.get -> System.Diagnostics.ActivityContext +OpenTelemetry.Context.Propagation.PropagationContext.Baggage.get -> OpenTelemetry.Baggage +OpenTelemetry.Context.Propagation.PropagationContext.Equals(OpenTelemetry.Context.Propagation.PropagationContext value) -> bool +OpenTelemetry.Context.Propagation.PropagationContext.PropagationContext() -> void +OpenTelemetry.Context.Propagation.PropagationContext.PropagationContext(System.Diagnostics.ActivityContext activityContext, OpenTelemetry.Baggage baggage) -> void +OpenTelemetry.Context.Propagation.Propagators +OpenTelemetry.Context.Propagation.TextMapPropagator +OpenTelemetry.Context.Propagation.TextMapPropagator.TextMapPropagator() -> void +OpenTelemetry.Context.Propagation.TraceContextPropagator +OpenTelemetry.Context.Propagation.TraceContextPropagator.TraceContextPropagator() -> void +OpenTelemetry.Context.RuntimeContext +OpenTelemetry.Context.RuntimeContextSlot +OpenTelemetry.Context.RuntimeContextSlot.Dispose() -> void +~OpenTelemetry.Context.RuntimeContextSlot.Name.get -> string +~OpenTelemetry.Context.RuntimeContextSlot.RuntimeContextSlot(string name) -> void +OpenTelemetry.Context.ThreadLocalRuntimeContextSlot +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.ThreadLocalRuntimeContextSlot(string name) -> void +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.get -> object +~OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Value.set -> void +OpenTelemetry.Metrics.IDeferredMeterProviderBuilder +~OpenTelemetry.Metrics.IDeferredMeterProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder +OpenTelemetry.Metrics.MeterProvider +OpenTelemetry.Metrics.MeterProvider.MeterProvider() -> void +OpenTelemetry.Metrics.MeterProviderBuilder +OpenTelemetry.Metrics.MeterProviderBuilder.MeterProviderBuilder() -> void +OpenTelemetry.Trace.ActivityExtensions +OpenTelemetry.Trace.IDeferredTracerProviderBuilder +~OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action configure) -> OpenTelemetry.Trace.TracerProviderBuilder +OpenTelemetry.Trace.Link +~OpenTelemetry.Trace.Link.Attributes.get -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Trace.Link.Context.get -> OpenTelemetry.Trace.SpanContext +OpenTelemetry.Trace.Link.Equals(OpenTelemetry.Trace.Link other) -> bool +OpenTelemetry.Trace.Link.Link() -> void +OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext) -> void +~OpenTelemetry.Trace.Link.Link(in OpenTelemetry.Trace.SpanContext spanContext, OpenTelemetry.Trace.SpanAttributes attributes) -> void +OpenTelemetry.Trace.SpanAttributes +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, bool[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, double[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, long[] values) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string value) -> void +~OpenTelemetry.Trace.SpanAttributes.Add(string key, string[] values) -> void +OpenTelemetry.Trace.SpanAttributes.SpanAttributes() -> void +~OpenTelemetry.Trace.SpanAttributes.SpanAttributes(System.Collections.Generic.IEnumerable> attributes) -> void +OpenTelemetry.Trace.SpanContext +OpenTelemetry.Trace.SpanContext.Equals(OpenTelemetry.Trace.SpanContext other) -> bool +OpenTelemetry.Trace.SpanContext.IsRemote.get -> bool +OpenTelemetry.Trace.SpanContext.IsValid.get -> bool +OpenTelemetry.Trace.SpanContext.SpanContext() -> void +OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityContext activityContext) -> void +~OpenTelemetry.Trace.SpanContext.SpanContext(in System.Diagnostics.ActivityTraceId traceId, in System.Diagnostics.ActivitySpanId spanId, System.Diagnostics.ActivityTraceFlags traceFlags, bool isRemote = false, System.Collections.Generic.IEnumerable> traceState = null) -> void +OpenTelemetry.Trace.SpanContext.SpanId.get -> System.Diagnostics.ActivitySpanId +OpenTelemetry.Trace.SpanContext.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags +OpenTelemetry.Trace.SpanContext.TraceId.get -> System.Diagnostics.ActivityTraceId +~OpenTelemetry.Trace.SpanContext.TraceState.get -> System.Collections.Generic.IEnumerable> +OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Client = 3 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Consumer = 5 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Internal = 1 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Producer = 4 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.SpanKind.Server = 2 -> OpenTelemetry.Trace.SpanKind +OpenTelemetry.Trace.Status +~OpenTelemetry.Trace.Status.Description.get -> string +OpenTelemetry.Trace.Status.Equals(OpenTelemetry.Trace.Status other) -> bool +OpenTelemetry.Trace.Status.Status() -> void +OpenTelemetry.Trace.Status.StatusCode.get -> OpenTelemetry.Trace.StatusCode +~OpenTelemetry.Trace.Status.WithDescription(string description) -> OpenTelemetry.Trace.Status +OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.StatusCode.Error = 2 -> OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.StatusCode.Ok = 1 -> OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.StatusCode.Unset = 0 -> OpenTelemetry.Trace.StatusCode +OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.AddEvent(string name, System.DateTimeOffset timestamp, OpenTelemetry.Trace.SpanAttributes attributes) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.TelemetrySpan.Context.get -> OpenTelemetry.Trace.SpanContext +OpenTelemetry.Trace.TelemetrySpan.Dispose() -> void +OpenTelemetry.Trace.TelemetrySpan.End() -> void +OpenTelemetry.Trace.TelemetrySpan.End(System.DateTimeOffset endTimestamp) -> void +OpenTelemetry.Trace.TelemetrySpan.IsRecording.get -> bool +OpenTelemetry.Trace.TelemetrySpan.ParentSpanId.get -> System.Diagnostics.ActivitySpanId +~OpenTelemetry.Trace.TelemetrySpan.RecordException(string type, string message, string stacktrace) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.RecordException(System.Exception ex) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, bool[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, double[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, int[] values) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string value) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.TelemetrySpan.SetAttribute(string key, string[] values) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.TelemetrySpan.SetStatus(OpenTelemetry.Trace.Status value) -> void +~OpenTelemetry.Trace.TelemetrySpan.UpdateName(string name) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.Tracer +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartActiveSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartRootSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind = OpenTelemetry.Trace.SpanKind.Internal, in OpenTelemetry.Trace.SpanContext parentContext = default(OpenTelemetry.Trace.SpanContext), OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +~OpenTelemetry.Trace.Tracer.StartSpan(string name, OpenTelemetry.Trace.SpanKind kind, in OpenTelemetry.Trace.TelemetrySpan parentSpan, OpenTelemetry.Trace.SpanAttributes initialAttributes = null, System.Collections.Generic.IEnumerable links = null, System.DateTimeOffset startTime = default(System.DateTimeOffset)) -> OpenTelemetry.Trace.TelemetrySpan +OpenTelemetry.Trace.TracerProvider +~OpenTelemetry.Trace.TracerProvider.GetTracer(string name, string version = null) -> OpenTelemetry.Trace.Tracer +OpenTelemetry.Trace.TracerProvider.TracerProvider() -> void +OpenTelemetry.Trace.TracerProviderBuilder +OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void +~override OpenTelemetry.Baggage.Equals(object obj) -> bool +override OpenTelemetry.Baggage.GetHashCode() -> int +override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Get() -> T +override OpenTelemetry.Context.AsyncLocalRuntimeContextSlot.Set(T value) -> void +~override OpenTelemetry.Context.Propagation.B3Propagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.B3Propagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.B3Propagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.BaggagePropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.CompositeTextMapPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +~override OpenTelemetry.Context.Propagation.PropagationContext.Equals(object obj) -> bool +override OpenTelemetry.Context.Propagation.PropagationContext.GetHashCode() -> int +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Extract(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Func> getter) -> OpenTelemetry.Context.Propagation.PropagationContext +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Fields.get -> System.Collections.Generic.ISet +~override OpenTelemetry.Context.Propagation.TraceContextPropagator.Inject(OpenTelemetry.Context.Propagation.PropagationContext context, T carrier, System.Action setter) -> void +override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Dispose(bool disposing) -> void +override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Get() -> T +override OpenTelemetry.Context.ThreadLocalRuntimeContextSlot.Set(T value) -> void +~override OpenTelemetry.Trace.Link.Equals(object obj) -> bool +override OpenTelemetry.Trace.Link.GetHashCode() -> int +~override OpenTelemetry.Trace.SpanContext.Equals(object obj) -> bool +override OpenTelemetry.Trace.SpanContext.GetHashCode() -> int +~override OpenTelemetry.Trace.Status.Equals(object obj) -> bool +override OpenTelemetry.Trace.Status.GetHashCode() -> int +~override OpenTelemetry.Trace.Status.ToString() -> string +static OpenTelemetry.ActivityContextExtensions.IsValid(this System.Diagnostics.ActivityContext ctx) -> bool +static OpenTelemetry.Baggage.ClearBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.Create(System.Collections.Generic.Dictionary baggageItems = null) -> OpenTelemetry.Baggage +static OpenTelemetry.Baggage.Current.get -> OpenTelemetry.Baggage +static OpenTelemetry.Baggage.Current.set -> void +~static OpenTelemetry.Baggage.GetBaggage(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.IReadOnlyDictionary +~static OpenTelemetry.Baggage.GetBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> string +~static OpenTelemetry.Baggage.GetEnumerator(OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> System.Collections.Generic.Dictionary.Enumerator +static OpenTelemetry.Baggage.operator !=(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool +static OpenTelemetry.Baggage.operator ==(OpenTelemetry.Baggage left, OpenTelemetry.Baggage right) -> bool +~static OpenTelemetry.Baggage.RemoveBaggage(string name, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(string name, string value, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +~static OpenTelemetry.Baggage.SetBaggage(System.Collections.Generic.IEnumerable> baggageItems, OpenTelemetry.Baggage baggage = default(OpenTelemetry.Baggage)) -> OpenTelemetry.Baggage +static OpenTelemetry.Context.Propagation.PropagationContext.operator !=(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool +static OpenTelemetry.Context.Propagation.PropagationContext.operator ==(OpenTelemetry.Context.Propagation.PropagationContext left, OpenTelemetry.Context.Propagation.PropagationContext right) -> bool +~static OpenTelemetry.Context.Propagation.Propagators.DefaultTextMapPropagator.get -> OpenTelemetry.Context.Propagation.TextMapPropagator +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.get -> System.Type +~static OpenTelemetry.Context.RuntimeContext.ContextSlotType.set -> void +~static OpenTelemetry.Context.RuntimeContext.GetSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> object +~static OpenTelemetry.Context.RuntimeContext.GetValue(string slotName) -> T +~static OpenTelemetry.Context.RuntimeContext.RegisterSlot(string slotName) -> OpenTelemetry.Context.RuntimeContextSlot +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, object value) -> void +~static OpenTelemetry.Context.RuntimeContext.SetValue(string slotName, T value) -> void +~static OpenTelemetry.Trace.ActivityExtensions.GetStatus(this System.Diagnostics.Activity activity) -> OpenTelemetry.Trace.Status +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex) -> void +~static OpenTelemetry.Trace.ActivityExtensions.SetStatus(this System.Diagnostics.Activity activity, OpenTelemetry.Trace.Status status) -> void +static OpenTelemetry.Trace.Link.operator !=(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool +static OpenTelemetry.Trace.Link.operator ==(OpenTelemetry.Trace.Link link1, OpenTelemetry.Trace.Link link2) -> bool +static OpenTelemetry.Trace.SpanContext.implicit operator System.Diagnostics.ActivityContext(OpenTelemetry.Trace.SpanContext spanContext) -> System.Diagnostics.ActivityContext +static OpenTelemetry.Trace.SpanContext.operator !=(OpenTelemetry.Trace.SpanContext spanContext1, OpenTelemetry.Trace.SpanContext spanContext2) -> bool +static OpenTelemetry.Trace.SpanContext.operator ==(OpenTelemetry.Trace.SpanContext spanContext1, OpenTelemetry.Trace.SpanContext spanContext2) -> bool +static OpenTelemetry.Trace.Status.operator !=(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool +static OpenTelemetry.Trace.Status.operator ==(OpenTelemetry.Trace.Status status1, OpenTelemetry.Trace.Status status2) -> bool +~static OpenTelemetry.Trace.Tracer.CurrentSpan.get -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.Tracer.WithSpan(OpenTelemetry.Trace.TelemetrySpan span) -> OpenTelemetry.Trace.TelemetrySpan +~static OpenTelemetry.Trace.TracerProvider.Default.get -> OpenTelemetry.Trace.TracerProvider +static readonly OpenTelemetry.Trace.Status.Error -> OpenTelemetry.Trace.Status +static readonly OpenTelemetry.Trace.Status.Ok -> OpenTelemetry.Trace.Status +static readonly OpenTelemetry.Trace.Status.Unset -> OpenTelemetry.Trace.Status +virtual OpenTelemetry.BaseProvider.Dispose(bool disposing) -> void +virtual OpenTelemetry.Context.RuntimeContextSlot.Dispose(bool disposing) -> void diff --git a/src/OpenTelemetry.Api/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Api/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..7a2d7df5780 --- /dev/null +++ b/src/OpenTelemetry.Api/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -0,0 +1,73 @@ +#nullable enable +abstract OpenTelemetry.Logs.Logger.EmitEvent(string! name, in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +abstract OpenTelemetry.Logs.Logger.EmitLog(in OpenTelemetry.Logs.LogRecordData data, in OpenTelemetry.Logs.LogRecordAttributeList attributes = default(OpenTelemetry.Logs.LogRecordAttributeList)) -> void +OpenTelemetry.InstrumentationScope +OpenTelemetry.InstrumentationScope.Attributes.get -> System.Collections.Generic.IReadOnlyDictionary? +OpenTelemetry.InstrumentationScope.Attributes.init -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope() -> void +OpenTelemetry.InstrumentationScope.InstrumentationScope(string? name) -> void +OpenTelemetry.InstrumentationScope.Name.get -> string! +OpenTelemetry.InstrumentationScope.SchemaUrl.get -> string? +OpenTelemetry.InstrumentationScope.SchemaUrl.init -> void +OpenTelemetry.InstrumentationScope.Version.get -> string? +OpenTelemetry.InstrumentationScope.Version.init -> void +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder +OpenTelemetry.Logs.IDeferredLoggerProviderBuilder.Configure(System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +OpenTelemetry.Logs.Logger +OpenTelemetry.Logs.Logger.Logger(OpenTelemetry.Logs.LoggerOptions! options) -> void +OpenTelemetry.Logs.Logger.Options.get -> OpenTelemetry.Logs.LoggerOptions! +OpenTelemetry.Logs.LoggerOptions +OpenTelemetry.Logs.LoggerOptions.EventDomain.get -> string? +OpenTelemetry.Logs.LoggerOptions.EventDomain.init -> void +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.get -> bool +OpenTelemetry.Logs.LoggerOptions.IncludeTraceContext.init -> void +OpenTelemetry.Logs.LoggerOptions.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope! +OpenTelemetry.Logs.LoggerOptions.LoggerOptions() -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(OpenTelemetry.InstrumentationScope! instrumentationScope) -> void +OpenTelemetry.Logs.LoggerOptions.LoggerOptions(string? name) -> void +OpenTelemetry.Logs.LoggerProvider +OpenTelemetry.Logs.LoggerProvider.GetLogger() -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.InstrumentationScope! instrumentationScope) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.GetLogger(string? name) -> OpenTelemetry.Logs.Logger! +OpenTelemetry.Logs.LoggerProvider.LoggerProvider() -> void +OpenTelemetry.Logs.LoggerProviderBuilder +OpenTelemetry.Logs.LoggerProviderBuilder.LoggerProviderBuilder() -> void +OpenTelemetry.Logs.LogRecordAttributeList +OpenTelemetry.Logs.LogRecordAttributeList.Add(string! key, object? value) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Add(System.Collections.Generic.KeyValuePair attribute) -> void +OpenTelemetry.Logs.LogRecordAttributeList.Count.get -> int +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Dispose() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.Enumerator() -> void +OpenTelemetry.Logs.LogRecordAttributeList.Enumerator.MoveNext() -> bool +OpenTelemetry.Logs.LogRecordAttributeList.GetEnumerator() -> OpenTelemetry.Logs.LogRecordAttributeList.Enumerator +OpenTelemetry.Logs.LogRecordAttributeList.LogRecordAttributeList() -> void +OpenTelemetry.Logs.LogRecordAttributeList.RecordException(System.Exception! exception) -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Logs.LogRecordAttributeList.this[int index].set -> void +OpenTelemetry.Logs.LogRecordAttributeList.this[string! key].set -> void +OpenTelemetry.Logs.LogRecordData +OpenTelemetry.Logs.LogRecordData.Body.get -> string? +OpenTelemetry.Logs.LogRecordData.Body.set -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData() -> void +OpenTelemetry.Logs.LogRecordData.LogRecordData(System.Diagnostics.Activity? activity) -> void +OpenTelemetry.Logs.LogRecordData.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecordData.Severity.set -> void +OpenTelemetry.Logs.LogRecordData.SpanId.get -> System.Diagnostics.ActivitySpanId +OpenTelemetry.Logs.LogRecordData.SpanId.set -> void +OpenTelemetry.Logs.LogRecordData.Timestamp.get -> System.DateTime +OpenTelemetry.Logs.LogRecordData.Timestamp.set -> void +OpenTelemetry.Logs.LogRecordData.TraceFlags.get -> System.Diagnostics.ActivityTraceFlags +OpenTelemetry.Logs.LogRecordData.TraceFlags.set -> void +OpenTelemetry.Logs.LogRecordData.TraceId.get -> System.Diagnostics.ActivityTraceId +OpenTelemetry.Logs.LogRecordData.TraceId.set -> void +OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Debug = 1 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Error = 4 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Fatal = 5 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Information = 2 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Trace = 0 -> OpenTelemetry.Logs.LogRecordSeverity +OpenTelemetry.Logs.LogRecordSeverity.Warning = 3 -> OpenTelemetry.Logs.LogRecordSeverity +~static OpenTelemetry.Trace.ActivityExtensions.RecordException(this System.Diagnostics.Activity activity, System.Exception ex, in System.Diagnostics.TagList tags) -> void +virtual OpenTelemetry.Logs.LoggerProvider.GetLogger(OpenTelemetry.Logs.LoggerOptions! options) -> OpenTelemetry.Logs.Logger! diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index 99bade8a2a9..032f654deb7 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased-Logs + +* Added `LoggerProvider` API from the OpenTelemetry specification + ([#3707](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3707)) + ## Unreleased * Updated to System.Diagnostics.DiagnosticSource version `7.0.0-rc.1.22426.10`. diff --git a/src/OpenTelemetry.Api/InstrumentationScope.cs b/src/OpenTelemetry.Api/InstrumentationScope.cs new file mode 100644 index 00000000000..1910e758dc2 --- /dev/null +++ b/src/OpenTelemetry.Api/InstrumentationScope.cs @@ -0,0 +1,67 @@ +// +// 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. +// + +#nullable enable + +using System.Collections.Generic; + +namespace OpenTelemetry; + +/// +/// Contains details about the library emitting telemetry. +/// +public sealed class InstrumentationScope +{ + /// + /// Initializes a new instance of the class. + /// + public InstrumentationScope() + : this(name: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Optional name identifying the instrumentation library. + public InstrumentationScope(string? name) + { + this.Name = string.IsNullOrWhiteSpace(name) + ? string.Empty + : name!; + } + + /// + /// Gets the name identifying the instrumentation library. + /// + public string Name { get; } + + /// + /// Gets the version of the instrumentation library. + /// + public string? Version { get; init; } + + /// + /// Gets the schema url of the instrumentation library. + /// + public string? SchemaUrl { get; init; } + + /// + /// Gets the attributes which should be associated with log records created + /// by the instrumentation library. + /// + public IReadOnlyDictionary? Attributes { get; init; } +} diff --git a/src/OpenTelemetry/Internal/Shims/IsExternalInit.cs b/src/OpenTelemetry.Api/Internal/Shims/IsExternalInit.cs similarity index 100% rename from src/OpenTelemetry/Internal/Shims/IsExternalInit.cs rename to src/OpenTelemetry.Api/Internal/Shims/IsExternalInit.cs diff --git a/src/OpenTelemetry/Internal/Shims/NullableAttributes.cs b/src/OpenTelemetry.Api/Internal/Shims/NullableAttributes.cs similarity index 100% rename from src/OpenTelemetry/Internal/Shims/NullableAttributes.cs rename to src/OpenTelemetry.Api/Internal/Shims/NullableAttributes.cs diff --git a/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs b/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs new file mode 100644 index 00000000000..5406a3eafec --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs @@ -0,0 +1,38 @@ +// +// 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. +// + +#nullable enable + +using System; + +namespace OpenTelemetry.Logs; + +/// +/// Describes a logger provider builder that supports deferred +/// initialization using an to perform +/// dependency injection. +/// +public interface IDeferredLoggerProviderBuilder +{ + /// + /// Register a callback action to configure the once the application is available. + /// + /// Configuration callback. + /// The supplied for chaining. + LoggerProviderBuilder Configure(Action configure); +} diff --git a/src/OpenTelemetry.Api/Logs/LogRecordAttributeList.cs b/src/OpenTelemetry.Api/Logs/LogRecordAttributeList.cs new file mode 100644 index 00000000000..7d9e761ec76 --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/LogRecordAttributeList.cs @@ -0,0 +1,322 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using OpenTelemetry.Internal; +using OpenTelemetry.Trace; + +namespace OpenTelemetry.Logs; + +/// +/// Stores attributes to be added to a log record. +/// +public struct LogRecordAttributeList : IReadOnlyList> +{ + internal const int OverflowMaxCount = 8; + internal const int OverflowAdditionalCapacity = 16; + internal List>? OverflowAttributes; + private KeyValuePair attribute1; + private KeyValuePair attribute2; + private KeyValuePair attribute3; + private KeyValuePair attribute4; + private KeyValuePair attribute5; + private KeyValuePair attribute6; + private KeyValuePair attribute7; + private KeyValuePair attribute8; + private int count; + + /// + public readonly int Count => this.count; + + /// + public KeyValuePair this[int index] + { + readonly get + { + if (this.OverflowAttributes is not null) + { + Debug.Assert(index < this.OverflowAttributes.Count, "Invalid index accessed."); + return this.OverflowAttributes[index]; + } + + if ((uint)index >= (uint)this.count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return index switch + { + 0 => this.attribute1, + 1 => this.attribute2, + 2 => this.attribute3, + 3 => this.attribute4, + 4 => this.attribute5, + 5 => this.attribute6, + 6 => this.attribute7, + 7 => this.attribute8, + _ => default, // we shouldn't come here anyway. + }; + } + + set + { + if (this.OverflowAttributes is not null) + { + Debug.Assert(index < this.OverflowAttributes.Count, "Invalid index accessed."); + this.OverflowAttributes[index] = value; + return; + } + + if ((uint)index >= (uint)this.count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + switch (index) + { + case 0: this.attribute1 = value; break; + case 1: this.attribute2 = value; break; + case 2: this.attribute3 = value; break; + case 3: this.attribute4 = value; break; + case 4: this.attribute5 = value; break; + case 5: this.attribute6 = value; break; + case 6: this.attribute7 = value; break; + case 7: this.attribute8 = value; break; + default: + Debug.Assert(false, "Unreachable code executed."); + break; + } + } + } + + /// + /// Add an attribute. + /// + /// Attribute name. + /// Attribute value. + [EditorBrowsable(EditorBrowsableState.Never)] + public object? this[string key] + { + // Note: This only exists to enable collection initializer syntax + // like { ["key"] = value }. + set => this.Add(new KeyValuePair(key, value)); + } + + /// + /// Add an attribute. + /// + /// Attribute name. + /// Attribute value. + public void Add(string key, object? value) + => this.Add(new KeyValuePair(key, value)); + + /// + /// Add an attribute. + /// + /// Attribute. + public void Add(KeyValuePair attribute) + { + if (this.OverflowAttributes is not null) + { + this.OverflowAttributes.Add(attribute); + this.count++; + return; + } + + Debug.Assert(this.count <= 8, "Item added beyond struct capacity."); + + switch (this.count) + { + case 0: this.attribute1 = attribute; break; + case 1: this.attribute2 = attribute; break; + case 2: this.attribute3 = attribute; break; + case 3: this.attribute4 = attribute; break; + case 4: this.attribute5 = attribute; break; + case 5: this.attribute6 = attribute; break; + case 6: this.attribute7 = attribute; break; + case 7: this.attribute8 = attribute; break; + case 8: + Debug.Assert(this.OverflowAttributes is null, "Overflow attributes already created."); + this.MoveAttributesToTheOverflowList(); + Debug.Assert(this.OverflowAttributes is not null, "Overflow attributes creation failure."); + this.OverflowAttributes!.Add(attribute); + break; + default: + // We shouldn't come here. + Debug.Assert(this.OverflowAttributes is null, "Unreachable code executed."); + return; + } + + this.count++; + } + + /// + /// Adds attributes representing an to the list. + /// + /// . + public void RecordException(Exception exception) + { + Guard.ThrowIfNull(exception); + + this.Add(SemanticConventions.AttributeExceptionType, exception.GetType().Name); + this.Add(SemanticConventions.AttributeExceptionMessage, exception.Message); + this.Add(SemanticConventions.AttributeExceptionStacktrace, exception.ToInvariantString()); + } + + /// + /// Returns an enumerator that iterates through the . + /// + /// . + public readonly Enumerator GetEnumerator() + => new(in this); + + /// + readonly IEnumerator> IEnumerable>.GetEnumerator() => this.GetEnumerator(); + + /// + readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + + internal List>? Export(ref List>? attributeStorage, int additionalCapacity = 0) + { + int count = this.count; + if (count + additionalCapacity <= 0) + { + return null; + } + + var overflowAttributes = this.OverflowAttributes; + if (overflowAttributes != null) + { + // An allocation has already occurred, just use the list. + return overflowAttributes; + } + + Debug.Assert(count <= 8, "Invalid size detected."); + + attributeStorage ??= new List>(OverflowAdditionalCapacity); + + // TODO: Perf test this, adjust as needed. + if (count > 0) + { + attributeStorage.Add(this.attribute1); + if (count == 1) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute2); + if (count == 2) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute3); + if (count == 3) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute4); + if (count == 4) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute5); + if (count == 5) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute6); + if (count == 6) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute7); + if (count == 7) + { + return attributeStorage; + } + + attributeStorage.Add(this.attribute8); + } + + return attributeStorage; + } + + private void MoveAttributesToTheOverflowList() + { + Debug.Assert(this.count == OverflowMaxCount, "count did not match OverflowMaxCount"); + + this.OverflowAttributes = new(OverflowAdditionalCapacity) + { + { this.attribute1 }, + { this.attribute2 }, + { this.attribute3 }, + { this.attribute4 }, + { this.attribute5 }, + { this.attribute6 }, + { this.attribute7 }, + { this.attribute8 }, + }; + } + + /// + /// Enumerates the elements of a . + /// + public struct Enumerator : IEnumerator>, IEnumerator + { + private LogRecordAttributeList attributes; + private int index; + + internal Enumerator(in LogRecordAttributeList attributes) + { + this.index = -1; + this.attributes = attributes; + } + + /// + public readonly KeyValuePair Current + => this.attributes[this.index]; + + /// + readonly object IEnumerator.Current => this.Current; + + /// + public bool MoveNext() + { + this.index++; + return this.index < this.attributes.Count; + } + + /// + public readonly void Dispose() + { + } + + /// + readonly void IEnumerator.Reset() + => throw new NotSupportedException(); + } +} diff --git a/src/OpenTelemetry.Api/Logs/LogRecordData.cs b/src/OpenTelemetry.Api/Logs/LogRecordData.cs new file mode 100644 index 00000000000..70df3e6c7bc --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/LogRecordData.cs @@ -0,0 +1,117 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Diagnostics; + +namespace OpenTelemetry.Logs; + +/// +/// Stores details about a log record. +/// +public struct LogRecordData +{ + internal DateTime TimestampBacking = DateTime.UtcNow; + + /// + /// Initializes a new instance of the struct. + /// + public LogRecordData() + : this(activity: null) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// + /// Note: The property is initialized to automatically. + /// + /// Optional used to populate context fields. + public LogRecordData(Activity? activity) + { + if (activity != null) + { + this.TraceId = activity.TraceId; + this.SpanId = activity.SpanId; + this.TraceFlags = activity.ActivityTraceFlags; + } + else + { + this.TraceId = default; + this.SpanId = default; + this.TraceFlags = ActivityTraceFlags.None; + } + } + + /// + /// Gets or sets the log timestamp. + /// + /// + /// Note: If is set to a value with it will be automatically converted to + /// UTC using . + /// + public DateTime Timestamp + { + readonly get => this.TimestampBacking; + set { this.TimestampBacking = value.Kind == DateTimeKind.Local ? value.ToUniversalTime() : value; } + } + + /// + /// Gets or sets the log . + /// + public ActivityTraceId TraceId { get; set; } + + /// + /// Gets or sets the log . + /// + public ActivitySpanId SpanId { get; set; } + + /// + /// Gets or sets the log . + /// + public ActivityTraceFlags TraceFlags { get; set; } + + /// + /// Gets or sets the log severity. + /// + public LogRecordSeverity? Severity { get; set; } = null; + + /// + /// Gets or sets the log body. + /// + public string? Body { get; set; } = null; + + internal static void SetActivityContext(ref LogRecordData data, Activity? activity = null) + { + if (activity != null) + { + data.TraceId = activity.TraceId; + data.SpanId = activity.SpanId; + data.TraceFlags = activity.ActivityTraceFlags; + } + else + { + data.TraceId = default; + data.SpanId = default; + data.TraceFlags = ActivityTraceFlags.None; + } + } +} diff --git a/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs b/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs new file mode 100644 index 00000000000..e5cfd0a897a --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs @@ -0,0 +1,43 @@ +// +// 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. +// + +#nullable enable + +namespace OpenTelemetry.Logs; + +/// +/// Describes the severity level of a log record. +/// +public enum LogRecordSeverity +{ + /// Trace severity. + Trace, + + /// Debug severity. + Debug, + + /// Information severity. + Information, + + /// Warning severity. + Warning, + + /// Error severity. + Error, + + /// Fatal severity. + Fatal, +} diff --git a/src/OpenTelemetry.Api/Logs/Logger.cs b/src/OpenTelemetry.Api/Logs/Logger.cs new file mode 100644 index 00000000000..0a9d1be477a --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/Logger.cs @@ -0,0 +1,63 @@ +// +// 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. +// + +#nullable enable + +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs; + +/// +/// Logger is the class responsible for creating log records. +/// +public abstract class Logger +{ + /// + /// Initializes a new instance of the class. + /// + /// . + protected Logger(LoggerOptions options) + { + Guard.ThrowIfNull(options); + + this.Options = options; + } + + /// + /// Gets the options associated with the logger. + /// + public LoggerOptions Options { get; } + + /// + /// Emit an event. + /// + /// Event name. + /// . + /// . + public abstract void EmitEvent( + string name, + in LogRecordData data, + in LogRecordAttributeList attributes = default); + + /// + /// Emit a log. + /// + /// . + /// . + public abstract void EmitLog( + in LogRecordData data, + in LogRecordAttributeList attributes = default); +} diff --git a/src/OpenTelemetry.Api/Logs/LoggerOptions.cs b/src/OpenTelemetry.Api/Logs/LoggerOptions.cs new file mode 100644 index 00000000000..28066389469 --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/LoggerOptions.cs @@ -0,0 +1,73 @@ +// +// 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. +// + +#nullable enable + +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs; + +/// +/// Contains options for the class. +/// +public sealed class LoggerOptions +{ + /// + /// Initializes a new instance of the class. + /// + public LoggerOptions() + : this(name: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Optional name identifying the instrumentation library. + public LoggerOptions(string? name) + : this(new InstrumentationScope(name)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// . + public LoggerOptions(InstrumentationScope instrumentationScope) + { + Guard.ThrowIfNull(instrumentationScope); + + this.InstrumentationScope = instrumentationScope; + } + + /// + /// Gets the for log + /// records emitted by the instrumentation library. + /// + public InstrumentationScope InstrumentationScope { get; } + + /// + /// Gets the domain of events emitted by the instrumentation library. + /// + public string? EventDomain { get; init; } + + /// + /// Gets a value indicating whether or not trace context should + /// automatically by injected into log records created by the + /// instrumentation library. + /// + public bool IncludeTraceContext { get; init; } = true; +} diff --git a/src/OpenTelemetry.Api/Logs/LoggerProvider.cs b/src/OpenTelemetry.Api/Logs/LoggerProvider.cs new file mode 100644 index 00000000000..ae2a0b8f7d4 --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/LoggerProvider.cs @@ -0,0 +1,67 @@ +// +// 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. +// + +#nullable enable + +namespace OpenTelemetry.Logs; + +/// +/// LoggerProvider is the entry point of the OpenTelemetry API. It provides access to . +/// +public class LoggerProvider : BaseProvider +{ + private NoopLogger? noopLogger; + + /// + /// Initializes a new instance of the class. + /// + protected LoggerProvider() + { + } + + /// + /// Gets a logger with the default options. + /// + /// instance. + public Logger GetLogger() + => this.GetLogger(name: null); + + /// + /// Gets a logger with the default options. + /// + /// Optional name identifying the instrumentation library. + /// instance. + public Logger GetLogger(string? name) + => this.GetLogger(new LoggerOptions(name)); + + /// + /// Gets a logger with the default options. + /// + /// . + /// instance. + public Logger GetLogger(InstrumentationScope instrumentationScope) + => this.GetLogger(new LoggerOptions(instrumentationScope)); + + /// + /// Gets a logger with the given options. + /// + /// Optional . + /// instance. + public virtual Logger GetLogger(LoggerOptions options) + { + return this.noopLogger ??= new(); + } +} diff --git a/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs b/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs new file mode 100644 index 00000000000..315e9d62719 --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs @@ -0,0 +1,32 @@ +// +// 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. +// + +#nullable enable + +namespace OpenTelemetry.Logs; + +/// +/// LoggerProviderBuilder base class. +/// +public abstract class LoggerProviderBuilder +{ + /// + /// Initializes a new instance of the class. + /// + protected LoggerProviderBuilder() + { + } +} diff --git a/src/OpenTelemetry.Api/Logs/NoopLogger.cs b/src/OpenTelemetry.Api/Logs/NoopLogger.cs new file mode 100644 index 00000000000..331eac6f15d --- /dev/null +++ b/src/OpenTelemetry.Api/Logs/NoopLogger.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. +// + +#nullable enable + +namespace OpenTelemetry.Logs; + +internal sealed class NoopLogger : Logger +{ + public NoopLogger() + : base(new(name: null)) + { + } + + public override void EmitEvent( + string name, + in LogRecordData data, + in LogRecordAttributeList attributes = default) + { + } + + public override void EmitLog( + in LogRecordData data, + in LogRecordAttributeList attributes = default) + { + } +} diff --git a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj index 56d15249d93..224d4c21497 100644 --- a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj +++ b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net462 + net6.0;netstandard2.1;netstandard2.0;net462 OpenTelemetry .NET API OpenTelemetry @@ -9,6 +9,11 @@ core- + + + false + + diff --git a/src/OpenTelemetry.Exporter.Console/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Console/.publicApi/net462/PublicAPI.Unshipped.txt index b9be4c9efb9..cdc524cfa1c 100644 --- a/src/OpenTelemetry.Exporter.Console/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Console/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,5 +1,8 @@ override OpenTelemetry.Exporter.ConsoleLogRecordExporter.Dispose(bool disposing) -> void *REMOVED*static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure = null) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions +static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions.AddConsoleExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action configureExporterAndMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder 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 b9be4c9efb9..cdc524cfa1c 100644 --- a/src/OpenTelemetry.Exporter.Console/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Console/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,8 @@ override OpenTelemetry.Exporter.ConsoleLogRecordExporter.Dispose(bool disposing) -> void *REMOVED*static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure = null) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions +static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions.AddConsoleExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action configureExporterAndMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md index bb8c842e3af..8fd6a47e48c 100644 --- a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased-Logs + +* Added overloads which accept a name to the `LoggerProviderBuilder` + `AddConsoleExporter` extension to allow for more fine-grained options + management + ([#3707](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3707)) + ## Unreleased * Changed the behavior of `ConsoleExporter`, the exporter will stop outputting diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs index 3754eb089fd..f0b2099d37e 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs @@ -15,6 +15,8 @@ // using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using OpenTelemetry.Exporter; using OpenTelemetry.Internal; @@ -23,20 +25,24 @@ namespace OpenTelemetry.Logs public static class ConsoleExporterLoggingExtensions { /// - /// Adds Console exporter with OpenTelemetryLoggerOptions. + /// Adds Console exporter to the OpenTelemetryLoggerOptions. /// - /// options to use. + /// . /// The instance of to chain the calls. + [Obsolete("Call the AddConsoleExporter extension using LoggerProviderBuilder instead this method will be removed in a future version.")] public static OpenTelemetryLoggerOptions AddConsoleExporter(this OpenTelemetryLoggerOptions loggerOptions) => AddConsoleExporter(loggerOptions, configure: null); /// - /// Adds Console exporter with OpenTelemetryLoggerOptions. + /// Adds Console exporter to the OpenTelemetryLoggerOptions. /// - /// options to use. + /// . /// Callback action for configuring . /// The instance of to chain the calls. - public static OpenTelemetryLoggerOptions AddConsoleExporter(this OpenTelemetryLoggerOptions loggerOptions, Action configure) + [Obsolete("Call the AddConsoleExporter extension using LoggerProviderBuilder instead this method will be removed in a future version.")] + public static OpenTelemetryLoggerOptions AddConsoleExporter( + this OpenTelemetryLoggerOptions loggerOptions, + Action configure) { Guard.ThrowIfNull(loggerOptions); @@ -44,5 +50,55 @@ public static OpenTelemetryLoggerOptions AddConsoleExporter(this OpenTelemetryLo configure?.Invoke(options); return loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(new ConsoleLogRecordExporter(options))); } + + /// + /// Adds Console exporter to the LoggerProviderBuilder. + /// + /// . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddConsoleExporter(this LoggerProviderBuilder builder) + => AddConsoleExporter(builder, name: null, configure: null); + + /// + /// Adds Console exporter to the LoggerProviderBuilder. + /// + /// . + /// Callback action for configuring . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddConsoleExporter( + this LoggerProviderBuilder builder, + Action configure) + => AddConsoleExporter(builder, name: null, configure); + + /// + /// Adds Console exporter to the LoggerProviderBuilder. + /// + /// . + /// Name which is used when retrieving options. + /// Callback action for configuring . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddConsoleExporter( + this LoggerProviderBuilder builder, + string name, + Action configure) + { + Guard.ThrowIfNull(builder); + + name ??= Options.DefaultName; + + if (configure != null) + { + builder.ConfigureServices(services => services.Configure(name, configure)); + } + + builder.ConfigureBuilder((sp, builder) => + { + var options = sp.GetRequiredService>().Get(name); + + builder.AddProcessor(new SimpleLogRecordExportProcessor(new ConsoleLogRecordExporter(options))); + }); + + return builder; + } } } diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs index f089b0e95a2..40220ffcc1d 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs @@ -70,33 +70,42 @@ public override ExportResult Export(in Batch batch) this.WriteLine($"{"LogRecord.TraceFlags:",-RightPaddingLength}{logRecord.TraceFlags}"); } + if (logRecord.TraceState != null) + { + this.WriteLine($"{"LogRecord.TraceState:",-RightPaddingLength}{logRecord.TraceState}"); + } + if (logRecord.CategoryName != null) { this.WriteLine($"{"LogRecord.CategoryName:",-RightPaddingLength}{logRecord.CategoryName}"); } - this.WriteLine($"{"LogRecord.LogLevel:",-RightPaddingLength}{logRecord.LogLevel}"); + if (logRecord.Severity.HasValue) + { + this.WriteLine($"{"LogRecord.Severity:",-RightPaddingLength}{logRecord.Severity}"); + } if (logRecord.FormattedMessage != null) { this.WriteLine($"{"LogRecord.FormattedMessage:",-RightPaddingLength}{logRecord.FormattedMessage}"); } - if (logRecord.State != null) + if (logRecord.Body != null) { - this.WriteLine($"{"LogRecord.State:",-RightPaddingLength}{logRecord.State}"); + this.WriteLine($"{"LogRecord.Body:",-RightPaddingLength}{logRecord.Body}"); } - else if (logRecord.StateValues != null) + + if (logRecord.Attributes != null) { - this.WriteLine("LogRecord.StateValues (Key:Value):"); - for (int i = 0; i < logRecord.StateValues.Count; i++) + this.WriteLine("LogRecord.Attributes (Key:Value):"); + for (int i = 0; i < logRecord.Attributes.Count; i++) { // Special casing {OriginalFormat} // See https://github.com/open-telemetry/opentelemetry-dotnet/pull/3182 // for explanation. - var valueToTransform = logRecord.StateValues[i].Key.Equals("{OriginalFormat}") - ? new KeyValuePair("OriginalFormat (a.k.a Body)", logRecord.StateValues[i].Value) - : logRecord.StateValues[i]; + var valueToTransform = logRecord.Attributes[i].Key.Equals("{OriginalFormat}") + ? new KeyValuePair("OriginalFormat (a.k.a Body)", logRecord.Attributes[i].Value) + : logRecord.Attributes[i]; if (ConsoleTagTransformer.Instance.TryTransformTag(valueToTransform, out var result)) { diff --git a/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt index a57d90fc54f..b7e4e7e13b2 100644 --- a/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.InMemory/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ override OpenTelemetry.Exporter.InMemoryExporter.Dispose(bool disposing) -> void +static OpenTelemetry.Logs.InMemoryExporterLoggingExtensions.AddInMemoryExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder 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 a57d90fc54f..b7e4e7e13b2 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 +1,4 @@ override OpenTelemetry.Exporter.InMemoryExporter.Dispose(bool disposing) -> void +static OpenTelemetry.Logs.InMemoryExporterLoggingExtensions.AddInMemoryExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Collections.Generic.ICollection exportedItems) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Collections.Generic.ICollection exportedItems, System.Action configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md index 744052f14ec..7a4d405fb02 100644 --- a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased-Logs + +* Added `LoggerProviderBuilder` `AddInMemoryExporter` extension + ([#3707](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3707)) + ## Unreleased * Changed error handling, `InMemoryExporter` will now throw diff --git a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs index c0cea4de63d..b162ff97ae9 100644 --- a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs +++ b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System; using System.Collections.Generic; using OpenTelemetry.Exporter; using OpenTelemetry.Internal; @@ -25,18 +26,39 @@ public static class InMemoryExporterLoggingExtensions /// /// Adds InMemory exporter to the OpenTelemetryLoggerOptions. /// - /// options to use. + /// . /// Collection which will be populated with the exported . /// The instance of to chain the calls. + [Obsolete("Call the AddInMemoryExporter extension using LoggerProviderBuilder instead this method will be removed in a future version.")] public static OpenTelemetryLoggerOptions AddInMemoryExporter(this OpenTelemetryLoggerOptions loggerOptions, ICollection exportedItems) { Guard.ThrowIfNull(loggerOptions); Guard.ThrowIfNull(exportedItems); + var logExporter = new InMemoryExporter( + exportFunc: (in Batch batch) => ExportLogRecord(in batch, exportedItems)); + + loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(logExporter)); + + return loggerOptions; + } + + /// + /// Adds InMemory exporter to the LoggerProviderBuilder. + /// + /// . + /// Collection which will be populated with the exported . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddInMemoryExporter(this LoggerProviderBuilder builder, ICollection exportedItems) + { + Guard.ThrowIfNull(builder); + Guard.ThrowIfNull(exportedItems); var logExporter = new InMemoryExporter( exportFunc: (in Batch batch) => ExportLogRecord(in batch, exportedItems)); - return loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(logExporter)); + builder.AddProcessor(new SimpleLogRecordExportProcessor(logExporter)); + + return builder; } private static ExportResult ExportLogRecord(in Batch batch, ICollection exportedItems) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/net462/PublicAPI.Unshipped.txt index 07a63e57297..69d71b6f18a 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,3 +1,6 @@ OpenTelemetry.Logs.OtlpLogExporterHelperExtensions +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 07a63e57297..69d71b6f18a 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,3 +1,6 @@ OpenTelemetry.Logs.OtlpLogExporterHelperExtensions +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt index 07a63e57297..69d71b6f18a 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -1,3 +1,6 @@ OpenTelemetry.Logs.OtlpLogExporterHelperExtensions +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder +static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.LoggerProviderBuilder builder, System.Action configure) -> OpenTelemetry.Logs.LoggerProviderBuilder static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md index dc3bdd72318..8c4e4cd620c 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased-Logs + +* Added overloads which accept a name to the `LoggerProviderBuilder` + `AddOtlpExporter` extension to allow for more fine-grained options + management + ([#3707](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3707)) + ## Unreleased * `OtlpExporterOptions` can now be bound to `IConfiguation` and diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OtlpLogExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OtlpLogExporterHelperExtensions.cs index ca2ca82b826..426ab70ab05 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OtlpLogExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/OtlpLogExporterHelperExtensions.cs @@ -15,7 +15,10 @@ // using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using OpenTelemetry.Exporter; +using OpenTelemetry.Internal; namespace OpenTelemetry.Logs { @@ -25,54 +28,120 @@ namespace OpenTelemetry.Logs public static class OtlpLogExporterHelperExtensions { /// - /// Adds OTLP Exporter as a configuration to the OpenTelemetry ILoggingBuilder. + /// Adds OTLP exporter to the OpenTelemetryLoggerOptions. /// - /// - /// options to use. + /// . /// The instance of to chain the calls. + [Obsolete("Call the AddOtlpExporter extension using LoggerProviderBuilder instead this method will be removed in a future version.")] public static OpenTelemetryLoggerOptions AddOtlpExporter(this OpenTelemetryLoggerOptions loggerOptions) => AddOtlpExporter(loggerOptions, configure: null); /// - /// Adds OTLP Exporter as a configuration to the OpenTelemetry ILoggingBuilder. + /// Adds OTLP exporter to the OpenTelemetryLoggerOptions. /// - /// - /// Note: AddOtlpExporter automatically sets to . - /// - /// options to use. + /// . /// Callback action for configuring . /// The instance of to chain the calls. + [Obsolete("Call the AddOtlpExporter extension using LoggerProviderBuilder instead this method will be removed in a future version.")] public static OpenTelemetryLoggerOptions AddOtlpExporter( this OpenTelemetryLoggerOptions loggerOptions, Action configure) - => AddOtlpExporter(loggerOptions, new(), configure); - - private static OpenTelemetryLoggerOptions AddOtlpExporter( - OpenTelemetryLoggerOptions loggerOptions, - OtlpExporterOptions exporterOptions, - Action configure) { + var exporterOptions = new OtlpExporterOptions(); configure?.Invoke(exporterOptions); var otlpExporter = new OtlpLogExporter(exporterOptions); - loggerOptions.ParseStateValues = true; + if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple) { - loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(otlpExporter)); + return loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(otlpExporter)); } else { - loggerOptions.AddProcessor(new BatchLogRecordExportProcessor( + return loggerOptions.AddProcessor(new BatchLogRecordExportProcessor( otlpExporter, exporterOptions.BatchExportProcessorOptions.MaxQueueSize, exporterOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds, exporterOptions.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, exporterOptions.BatchExportProcessorOptions.MaxExportBatchSize)); } + } + + /// + /// Adds OTLP exporter to the LoggerProviderBuilder. + /// + /// . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddOtlpExporter(this LoggerProviderBuilder builder) + => AddOtlpExporter(builder, name: null, configure: null); + + /// + /// Adds OTLP exporter to the LoggerProviderBuilder. + /// + /// . + /// Callback action for configuring . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddOtlpExporter( + this LoggerProviderBuilder builder, + Action configure) + => AddOtlpExporter(builder, name: null, configure); - return loggerOptions; + /// + /// Adds OTLP exporter to the LoggerProviderBuilder. + /// + /// . + /// Name which is used when retrieving options. + /// Callback action for configuring . + /// The instance of to chain the calls. + public static LoggerProviderBuilder AddOtlpExporter( + this LoggerProviderBuilder builder, + string name, + Action configure) + { + Guard.ThrowIfNull(builder); + + name ??= Options.DefaultName; + + if (configure != null) + { + builder.ConfigureServices(services => services.Configure(name, configure)); + } + + builder.ConfigureBuilder((sp, builder) => + { + var options = sp.GetRequiredService>().Get(name); + + AddOtlpExporter(builder, options, sp); + }); + + return builder; + } + + private static void AddOtlpExporter( + LoggerProviderBuilder builder, + OtlpExporterOptions exporterOptions, + IServiceProvider serviceProvider) + { + exporterOptions.TryEnableIHttpClientFactoryIntegration(serviceProvider, "OtlpLogExporter"); + var otlpExporter = new OtlpLogExporter(exporterOptions); + + if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple) + { + builder.AddProcessor(new SimpleLogRecordExportProcessor(otlpExporter)); + } + else + { + // TODO: exporterOptions.BatchExportProcessorOptions is + // BatchExportActivityProcessorOptions which is using tracing + // environment variables. There should probably be a dedicated + // setting for logs using BatchExportLogRecordProcessorOptions + builder.AddProcessor(new BatchLogRecordExportProcessor( + otlpExporter, + exporterOptions.BatchExportProcessorOptions.MaxQueueSize, + exporterOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds, + exporterOptions.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, + exporterOptions.BatchExportProcessorOptions.MaxExportBatchSize)); + } } } } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/ApiCompatBaseline.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/ApiCompatBaseline.txt deleted file mode 100644 index e7158253a98..00000000000 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/ApiCompatBaseline.txt +++ /dev/null @@ -1,4 +0,0 @@ -Compat issues with assembly OpenTelemetry.Exporter.OpenTelemetryProtocol: -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' exists on 'OpenTelemetry.Exporter.OtlpExporterOptions.Endpoint.get()' in the contract but not the implementation. -CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' exists on 'OpenTelemetry.Exporter.OtlpExporterOptions.Endpoint.set(System.Uri)' in the contract but not the implementation. -Total Issues: 2 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs index c5a24dfa2a4..90a2007a669 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs @@ -99,7 +99,7 @@ internal static ScopeSpans GetSpanListFromPool(string name, string version) { spans = new ScopeSpans { - Scope = new InstrumentationScope + Scope = new Proto.Common.V1.InstrumentationScope { Name = name, // Name is enforced to not be null, but it can be empty. Version = version ?? string.Empty, // NRE throw by proto diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs index 126530af082..35accb644cb 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs @@ -19,7 +19,6 @@ using System.Runtime.CompilerServices; using Google.Protobuf; using Google.Protobuf.Collections; -using Microsoft.Extensions.Logging; using OpenTelemetry.Internal; using OpenTelemetry.Logs; using OpenTelemetry.Trace; @@ -32,9 +31,9 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation { internal static class LogRecordExtensions { - private static readonly string[] LogLevels = new string[7] + private static readonly string[] SeverityTextMapping = new string[] { - "Trace", "Debug", "Information", "Warning", "Error", "Critical", "None", + null, "Trace", "Debug", "Information", "Warning", "Error", "Fatal", }; internal static void AddBatch( @@ -71,8 +70,8 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) otlpLogRecord = new OtlpLogs.LogRecord { TimeUnixNano = (ulong)logRecord.Timestamp.ToUnixTimeNanoseconds(), - SeverityNumber = GetSeverityNumber(logRecord.LogLevel), - SeverityText = LogLevels[(int)logRecord.LogLevel], + SeverityNumber = GetSeverityNumber(logRecord.Severity), + SeverityText = SeverityTextMapping[logRecord.Severity.HasValue ? ((int)logRecord.Severity.Value) + 1 : 0], }; if (!string.IsNullOrEmpty(logRecord.CategoryName)) @@ -92,18 +91,18 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) bodyPopulatedFromFormattedMessage = true; } - if (logRecord.StateValues != null) + if (logRecord.Attributes != null) { - foreach (var stateValue in logRecord.StateValues) + foreach (var attribute in logRecord.Attributes) { // Special casing {OriginalFormat} // See https://github.com/open-telemetry/opentelemetry-dotnet/pull/3182 // for explanation. - if (stateValue.Key.Equals("{OriginalFormat}") && !bodyPopulatedFromFormattedMessage) + if (attribute.Key.Equals("{OriginalFormat}") && !bodyPopulatedFromFormattedMessage) { - otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = stateValue.Value as string }; + otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = attribute.Value as string }; } - else if (OtlpKeyValueTransformer.Instance.TryTransformTag(stateValue, out var result)) + else if (OtlpKeyValueTransformer.Instance.TryTransformTag(attribute, out var result)) { otlpLogRecord.Attributes.Add(result); } @@ -183,34 +182,36 @@ private static void AddIntAttribute(this RepeatedField repe } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static OtlpLogs.SeverityNumber GetSeverityNumber(LogLevel logLevel) + private static OtlpLogs.SeverityNumber GetSeverityNumber(LogRecordSeverity? severity) { - // Maps the ILogger LogLevel to OpenTelemetry logging level. - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#appendix-b-severitynumber-example-mappings + if (!severity.HasValue) + { + return OtlpLogs.SeverityNumber.Unspecified; + } + // TODO: for improving perf simply do ((int)loglevel * 4) + 1 // or ((int)logLevel << 2) + 1 // Current code is just for ease of reading. - switch (logLevel) + switch (severity.Value) { - case LogLevel.Trace: + case LogRecordSeverity.Trace: return OtlpLogs.SeverityNumber.Trace; - case LogLevel.Debug: + case LogRecordSeverity.Debug: return OtlpLogs.SeverityNumber.Debug; - case LogLevel.Information: + case LogRecordSeverity.Information: return OtlpLogs.SeverityNumber.Info; - case LogLevel.Warning: + case LogRecordSeverity.Warning: return OtlpLogs.SeverityNumber.Warn; - case LogLevel.Error: + case LogRecordSeverity.Error: return OtlpLogs.SeverityNumber.Error; - case LogLevel.Critical: + case LogRecordSeverity.Fatal: return OtlpLogs.SeverityNumber.Fatal; // TODO: - // we reach default only for LogLevel.None - // but that is filtered out anyway. - // should we throw here then? + // we reach default only for invalid/unknown values should we + // throw here then? default: - return OtlpLogs.SeverityNumber.Debug; + return OtlpLogs.SeverityNumber.Trace; } } } diff --git a/src/OpenTelemetry.Extensions.EventSource/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..7dc5c58110b --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net462/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/OpenTelemetry.Extensions.EventSource/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..4f8d302c3f0 --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,11 @@ +#nullable enable +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.OpenTelemetryEventSourceLogEmitter(OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Func! shouldListenToFunc, OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions? options = null, bool disposeProvider = false) -> void +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions.IncludeFormattedMessage.get -> bool +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions.IncludeFormattedMessage.set -> void +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions.OpenTelemetryEventSourceLogEmitterOptions() -> void +OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerProviderBuilderExtensions +override OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.Dispose() -> void +static OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerProviderBuilderExtensions.AddEventSourceLogEmitter(this OpenTelemetry.Logs.LoggerProviderBuilder! builder, System.Func! shouldListenToFunc) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerProviderBuilderExtensions.AddEventSourceLogEmitter(this OpenTelemetry.Logs.LoggerProviderBuilder! builder, System.Func! shouldListenToFunc, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! diff --git a/src/OpenTelemetry.Extensions.EventSource/.publicApi/net6.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net6.0/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..7dc5c58110b --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net6.0/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/OpenTelemetry.Extensions.EventSource/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net6.0/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..4f8d302c3f0 --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -0,0 +1,11 @@ +#nullable enable +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.OpenTelemetryEventSourceLogEmitter(OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Func! shouldListenToFunc, OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions? options = null, bool disposeProvider = false) -> void +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions.IncludeFormattedMessage.get -> bool +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions.IncludeFormattedMessage.set -> void +OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitterOptions.OpenTelemetryEventSourceLogEmitterOptions() -> void +OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerProviderBuilderExtensions +override OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.Dispose() -> void +static OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerProviderBuilderExtensions.AddEventSourceLogEmitter(this OpenTelemetry.Logs.LoggerProviderBuilder! builder, System.Func! shouldListenToFunc) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerProviderBuilderExtensions.AddEventSourceLogEmitter(this OpenTelemetry.Logs.LoggerProviderBuilder! builder, System.Func! shouldListenToFunc, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! diff --git a/src/OpenTelemetry.Extensions.EventSource/AssemblyInfo.cs b/src/OpenTelemetry.Extensions.EventSource/AssemblyInfo.cs new file mode 100644 index 00000000000..1aa11097133 --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/AssemblyInfo.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. +// + +using System; +using System.Runtime.CompilerServices; + +[assembly: CLSCompliant(false)] +[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.EventSource.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.Extensions.EventSource/CHANGELOG.md b/src/OpenTelemetry.Extensions.EventSource/CHANGELOG.md new file mode 100644 index 00000000000..63bfc986bdc --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## Unreleased + +Initial release. diff --git a/src/OpenTelemetry.Extensions.EventSource/OpenTelemetry.Extensions.EventSource.csproj b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetry.Extensions.EventSource.csproj new file mode 100644 index 00000000000..68e45111409 --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetry.Extensions.EventSource.csproj @@ -0,0 +1,19 @@ + + + + net6.0;net462 + Extensions for using OpenTelemetry with System.Diagnostics.Tracing.EventSource + enable + AllEnabledByDefault + latest + + + + + + + + + + + diff --git a/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLogEmitter.cs b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLogEmitter.cs new file mode 100644 index 00000000000..270522590ed --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLogEmitter.cs @@ -0,0 +1,232 @@ +// +// 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.Diagnostics.Tracing; +using System.Globalization; +using System.Linq; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + /// + /// Implements an which will convert events into OpenTelemetry logs. + /// + public sealed class OpenTelemetryEventSourceLogEmitter : EventListener + { + private readonly bool includeFormattedMessage; + private readonly LoggerProvider loggerProvider; + private readonly object lockObj = new(); + private readonly Func shouldListenToFunc; + private readonly List eventSources = new(); + private readonly List? eventSourcesBeforeConstructor = new(); + private readonly bool disposeProvider; + private readonly Logger logger; + + /// + /// Initializes a new instance of the class. + /// + /// . + /// Callback function used to decide if + /// events should be captured for a given . Return if no + /// events should be captured. + /// . + /// Controls whether or not the supplied + /// will be disposed when + /// the is disposed. Default value: . + public OpenTelemetryEventSourceLogEmitter( + LoggerProvider loggerProvider, + Func shouldListenToFunc, + OpenTelemetryEventSourceLogEmitterOptions? options = null, + bool disposeProvider = false) + { + Guard.ThrowIfNull(loggerProvider); + Guard.ThrowIfNull(shouldListenToFunc); + + options ??= new(); + + this.includeFormattedMessage = options.IncludeFormattedMessage; + this.loggerProvider = loggerProvider!; + this.disposeProvider = disposeProvider; + this.shouldListenToFunc = shouldListenToFunc; + + this.logger = loggerProvider.GetLogger(new LoggerOptions( + new InstrumentationScope("OpenTelemetry.Extensions.EventSource") + { + Version = $"semver:{typeof(OpenTelemetryEventSourceLogEmitter).Assembly.GetName().Version}", + })); + + lock (this.lockObj) + { + foreach (EventSource eventSource in this.eventSourcesBeforeConstructor) + { + this.ProcessSource(eventSource); + } + + this.eventSourcesBeforeConstructor = null; + } + } + + /// + public override void Dispose() + { + foreach (EventSource eventSource in this.eventSources) + { + this.DisableEvents(eventSource); + } + + this.eventSources.Clear(); + + if (this.disposeProvider) + { + this.loggerProvider.Dispose(); + } + + base.Dispose(); + } + +#pragma warning disable CA1062 // Validate arguments of public methods + /// + protected override void OnEventSourceCreated(EventSource eventSource) + { + Debug.Assert(eventSource != null, "EventSource was null."); + + try + { + if (this.eventSourcesBeforeConstructor != null) + { + lock (this.lockObj) + { + if (this.eventSourcesBeforeConstructor != null) + { + this.eventSourcesBeforeConstructor.Add(eventSource!); + return; + } + } + } + + this.ProcessSource(eventSource!); + } + finally + { + base.OnEventSourceCreated(eventSource); + } + } +#pragma warning restore CA1062 // Validate arguments of public methods + +#pragma warning disable CA1062 // Validate arguments of public methods + /// + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + Debug.Assert(eventData != null, "EventData was null."); + + string? rawMessage = eventData!.Message; + + LogRecordData data = new(Activity.Current) + { +#if !NETFRAMEWORK + Timestamp = eventData.TimeStamp, +#endif + Severity = ConvertEventLevelToLogLevel(eventData.Level), + }; + + LogRecordAttributeList attributes = default; + + attributes.Add("event_source.name", eventData.EventSource.Name); + attributes.Add("event_source.event_id", eventData.EventId); + attributes.Add("event_source.event_name", eventData.EventName); + + if (eventData.ActivityId != Guid.Empty) + { + attributes.Add("event_source.activity_id", eventData.ActivityId); + } + + if (eventData.RelatedActivityId != Guid.Empty) + { + attributes.Add("event_source.related_activity_id", eventData.RelatedActivityId); + } + + int payloadCount = eventData.Payload?.Count ?? 0; + + if (payloadCount > 0 && payloadCount == eventData.PayloadNames?.Count) + { + for (int i = 0; i < payloadCount; i++) + { + string name = eventData.PayloadNames[i]; + + if (!string.IsNullOrEmpty(rawMessage)) + { + // TODO: This code converts the event message from + // string.Format syntax (eg: "Some message {0} {1}") + // into structured log format (eg: "Some message + // {propertyName1} {propertyName2}") but it is + // expensive. Probably needs a cache. +#if NETFRAMEWORK + rawMessage = rawMessage.Replace($"{{{i}}}", $"{{{name}}}"); +#else + rawMessage = rawMessage.Replace($"{{{i}}}", $"{{{name}}}", StringComparison.Ordinal); +#endif + } + + attributes.Add(name, eventData.Payload![i]); + } + } + + if (!string.IsNullOrEmpty(rawMessage)) + { + data.Body = rawMessage; + + if (this.includeFormattedMessage && payloadCount > 0) + { + attributes.Add("event_source.formatted_message", string.Format(CultureInfo.InvariantCulture, eventData.Message!, eventData.Payload!.ToArray())); + } + } + + this.logger.EmitLog(in data, in attributes); + } +#pragma warning restore CA1062 // Validate arguments of public methods + + private static LogRecordSeverity ConvertEventLevelToLogLevel(EventLevel eventLevel) + { + return eventLevel switch + { + EventLevel.Informational => LogRecordSeverity.Information, + EventLevel.Warning => LogRecordSeverity.Warning, + EventLevel.Error => LogRecordSeverity.Error, + EventLevel.Critical => LogRecordSeverity.Fatal, + _ => LogRecordSeverity.Trace, + }; + } + + private void ProcessSource(EventSource eventSource) + { + EventLevel? eventLevel = this.shouldListenToFunc(eventSource.Name); + + if (eventLevel.HasValue) + { + this.eventSources.Add(eventSource); + this.EnableEvents(eventSource, eventLevel.Value, EventKeywords.All); + } + } + } +} diff --git a/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLogEmitterOptions.cs b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLogEmitterOptions.cs new file mode 100644 index 00000000000..254909b095f --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLogEmitterOptions.cs @@ -0,0 +1,31 @@ +// +// 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.Logs; + +/// +/// Contains options that apply to log messages written through the . +/// +public class OpenTelemetryEventSourceLogEmitterOptions +{ + /// + /// Gets or sets a value indicating whether or not formatted log message + /// should be included on generated s. Default + /// value: . + /// + public bool IncludeFormattedMessage { get; set; } +} diff --git a/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLoggerProviderBuilderExtensions.cs b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLoggerProviderBuilderExtensions.cs new file mode 100644 index 00000000000..fda8cadadd1 --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/OpenTelemetryEventSourceLoggerProviderBuilderExtensions.cs @@ -0,0 +1,88 @@ +// +// 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; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + /// + /// Contains extension methods for registering OpenTelemetry EventSource utilities into logging services. + /// + public static class OpenTelemetryEventSourceLoggerProviderBuilderExtensions + { + /// + /// Registers an which will convert events into OpenTelemetry logs. + /// + /// . + /// + /// Supplied for + /// chaining calls. + public static LoggerProviderBuilder AddEventSourceLogEmitter( + this LoggerProviderBuilder builder, + Func shouldListenToFunc) + => AddEventSourceLogEmitter(builder, shouldListenToFunc, name: null, configure: null); + + /// + /// Registers an which will convert events into OpenTelemetry logs. + /// + /// . + /// Callback function used to decide if + /// events should be captured for a given . Return if no + /// events should be captured. + /// Optional name which is used when retrieving options. + /// Optional callback action for configuring . + /// Supplied for + /// chaining calls. + public static LoggerProviderBuilder AddEventSourceLogEmitter( + this LoggerProviderBuilder builder, + Func shouldListenToFunc, + string? name, + Action? configure) + { + Guard.ThrowIfNull(builder); + Guard.ThrowIfNull(shouldListenToFunc); + + name ??= Options.DefaultName; + + if (configure != null) + { + builder.ConfigureServices(services => services.Configure(configure)); + } + + builder.AddInstrumentation((sp, provider) => + new OpenTelemetryEventSourceLogEmitter( + provider, + shouldListenToFunc, + sp.GetRequiredService>().Get(name), + disposeProvider: false)); + + return builder; + } + } +} diff --git a/src/OpenTelemetry.Extensions.EventSource/README.md b/src/OpenTelemetry.Extensions.EventSource/README.md new file mode 100644 index 00000000000..b88f146a0eb --- /dev/null +++ b/src/OpenTelemetry.Extensions.EventSource/README.md @@ -0,0 +1,61 @@ +# OpenTelemetry.Extensions.EventSource + +[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Extensions.EventSource.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.EventSource) +[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Extensions.EventSource.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.EventSource) + +This project contains an +[EventListener](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlistener) +which can be used to translate events written to an +[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource) +into OpenTelemetry logs. + +## Installation + +```shell +dotnet add package OpenTelemetry.Extensions.EventSource --prerelease +``` + +## Usage Example + +### Configured using dependency injection + +```csharp +IHost host = Host.CreateDefaultBuilder(args) + .ConfigureLogging(builder => + { + builder.ClearProviders(); + + // Step 1: Configure OpenTelemetry logging... + builder.AddOpenTelemetry(options => + { + options + .ConfigureResource(builder => builder.AddService("MyService")) + .AddConsoleExporter() + // Step 2: Register OpenTelemetryEventSourceLogEmitter to listen to events... + .AddEventSourceLogEmitter((name) => name == MyEventSource.Name ? EventLevel.Informational : null); + }); + }) + .Build(); + + host.Run(); +``` + +### Configured manually + +```csharp +// Step 1: Configure OpenTelemetryLoggerProvider... +var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .ConfigureResource(builder => builder.AddService("MyService")) + .AddConsoleExporter() + .Build(); + +// Step 2: Create OpenTelemetryEventSourceLogEmitter to listen to events... +using var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => name == MyEventSource.Name ? EventLevel.Informational : null, + disposeProvider: true); +``` + +## References + +* [OpenTelemetry Project](https://opentelemetry.io/) diff --git a/src/OpenTelemetry.Extensions.Serilog/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..7dc5c58110b --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net462/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/OpenTelemetry.Extensions.Serilog/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..518160e9a3d --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,7 @@ +#nullable enable +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions.IncludeRenderedMessage.get -> bool +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions.IncludeRenderedMessage.set -> void +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions.OpenTelemetrySerilogSinkOptions() -> void +Serilog.OpenTelemetrySerilogExtensions +static Serilog.OpenTelemetrySerilogExtensions.OpenTelemetry(this Serilog.Configuration.LoggerSinkConfiguration! loggerConfiguration, OpenTelemetry.Logs.LoggerProvider! loggerProvider, OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions? options = null, bool disposeProvider = false) -> Serilog.LoggerConfiguration! diff --git a/src/OpenTelemetry.Extensions.Serilog/.publicApi/net6.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net6.0/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..7dc5c58110b --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net6.0/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/OpenTelemetry.Extensions.Serilog/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net6.0/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..518160e9a3d --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -0,0 +1,7 @@ +#nullable enable +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions.IncludeRenderedMessage.get -> bool +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions.IncludeRenderedMessage.set -> void +OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions.OpenTelemetrySerilogSinkOptions() -> void +Serilog.OpenTelemetrySerilogExtensions +static Serilog.OpenTelemetrySerilogExtensions.OpenTelemetry(this Serilog.Configuration.LoggerSinkConfiguration! loggerConfiguration, OpenTelemetry.Logs.LoggerProvider! loggerProvider, OpenTelemetry.Logs.OpenTelemetrySerilogSinkOptions? options = null, bool disposeProvider = false) -> Serilog.LoggerConfiguration! diff --git a/src/OpenTelemetry.Extensions.Serilog/AssemblyInfo.cs b/src/OpenTelemetry.Extensions.Serilog/AssemblyInfo.cs new file mode 100644 index 00000000000..a51a83d9d1d --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/AssemblyInfo.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 System; +using System.Runtime.CompilerServices; + +[assembly: CLSCompliant(false)] +[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.Extensions.Serilog/CHANGELOG.md b/src/OpenTelemetry.Extensions.Serilog/CHANGELOG.md new file mode 100644 index 00000000000..63bfc986bdc --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## Unreleased + +Initial release. diff --git a/src/OpenTelemetry.Extensions.Serilog/OpenTelemetry.Extensions.Serilog.csproj b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetry.Extensions.Serilog.csproj new file mode 100644 index 00000000000..d74af369b30 --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetry.Extensions.Serilog.csproj @@ -0,0 +1,24 @@ + + + + net6.0;net462 + Extensions to enable OpenTelemetry logging when using the Serilog library + $(PackageTags);serilog;logging + enable + AllEnabledByDefault + latest + + + + + + + + + + + + + + + diff --git a/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogExtensions.cs b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogExtensions.cs new file mode 100644 index 00000000000..622f8f7a241 --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogExtensions.cs @@ -0,0 +1,56 @@ +// +// 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 OpenTelemetry.Internal; +using OpenTelemetry.Logs; +using Serilog.Configuration; + +namespace Serilog +{ + /// + /// Contains Serilog extension methods. + /// + public static class OpenTelemetrySerilogExtensions + { + /// + /// Adds a sink to Serilog which will + /// write to OpenTelemetry. + /// + /// . + /// . + /// . + /// Controls whether or not the supplied + /// will be disposed when + /// the logger is disposed. Default value: . + /// Supplied for chaining calls. + public static LoggerConfiguration OpenTelemetry( + this LoggerSinkConfiguration loggerConfiguration, + LoggerProvider loggerProvider, + OpenTelemetrySerilogSinkOptions? options = null, + bool disposeProvider = false) + { + Guard.ThrowIfNull(loggerConfiguration); + Guard.ThrowIfNull(loggerProvider); + +#pragma warning disable CA2000 // Dispose objects before losing scope + return loggerConfiguration.Sink(new OpenTelemetrySerilogSink(loggerProvider, options, disposeProvider)); +#pragma warning restore CA2000 // Dispose objects before losing scope + } + } +} diff --git a/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogSink.cs b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogSink.cs new file mode 100644 index 00000000000..c02c4bb2dd2 --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogSink.cs @@ -0,0 +1,145 @@ +// +// 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 Serilog.Core; +using Serilog.Events; + +namespace OpenTelemetry.Logs +{ + internal sealed class OpenTelemetrySerilogSink : ILogEventSink, IDisposable + { + private readonly LoggerProvider loggerProvider; + private readonly bool includeRenderedMessage; + private readonly Logger logger; + private readonly bool disposeProvider; + + public OpenTelemetrySerilogSink( + LoggerProvider loggerProvider, + OpenTelemetrySerilogSinkOptions? options, + bool disposeProvider) + { + Debug.Assert(loggerProvider != null, "loggerProvider was null"); + + options ??= new(); + + this.loggerProvider = loggerProvider!; + this.disposeProvider = disposeProvider; + + this.logger = loggerProvider!.GetLogger(new LoggerOptions( + new InstrumentationScope("OpenTelemetry.Extensions.Serilog") + { + Version = $"semver:{typeof(OpenTelemetrySerilogSink).Assembly.GetName().Version}", + })); + + this.includeRenderedMessage = options.IncludeRenderedMessage; + } + + public void Emit(LogEvent logEvent) + { + Debug.Assert(logEvent != null, "LogEvent was null."); + + LogRecordData data = new(Activity.Current) + { + Timestamp = logEvent!.Timestamp.UtcDateTime, + Severity = (LogRecordSeverity)(int)logEvent.Level, + Body = logEvent.MessageTemplate.Text, + }; + + LogRecordAttributeList attributes = default; + + if (this.includeRenderedMessage) + { + attributes.Add("serilog.rendered_message", logEvent.RenderMessage()); + } + + var exception = logEvent.Exception; + if (exception != null) + { + attributes.RecordException(exception); + } + + foreach (KeyValuePair property in logEvent.Properties) + { + // TODO: Serilog supports complex type logging. This is not yet + // supported in OpenTelemetry. + if (property.Key == Constants.SourceContextPropertyName + && property.Value is ScalarValue sourceContextValue) + { + attributes.Add("serilog.source_context", sourceContextValue.Value as string); + } + else if (property.Value is ScalarValue scalarValue) + { + attributes.Add(property.Key, scalarValue.Value); + } + else if (property.Value is SequenceValue sequenceValue) + { + IReadOnlyList elements = sequenceValue.Elements; + if (elements.Count > 0) + { + // Note: The goal here is to build a typed array (eg + // int[]) if all the element types match otherwise + // fallback to object[] + + Type? elementType = null; + Array? values = null; + + for (int i = 0; i < elements.Count; i++) + { + if (elements[i] is ScalarValue value) + { + Type currentElementType = value.Value?.GetType() ?? typeof(object); + + if (values == null) + { + elementType = currentElementType; + values = Array.CreateInstance(elementType, elements.Count); + } + else if (!elementType!.IsAssignableFrom(currentElementType)) + { + // Array with mixed types detected + object[] newValues = new object[elements.Count]; + values.CopyTo(newValues, 0); + values = newValues; + elementType = typeof(object); + } + + values.SetValue(value.Value, i); + } + } + + if (values != null) + { + attributes.Add(property.Key, values); + } + } + } + } + + this.logger.EmitLog(in data, in attributes); + } + + public void Dispose() + { + if (this.disposeProvider) + { + this.loggerProvider.Dispose(); + } + } + } +} diff --git a/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogSinkOptions.cs b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogSinkOptions.cs new file mode 100644 index 00000000000..d9a3d711fd3 --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/OpenTelemetrySerilogSinkOptions.cs @@ -0,0 +1,30 @@ +// +// 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.Logs; + +/// +/// Contains options that apply to log messages written through the OpenTelemetry Serilog sink. +/// +public class OpenTelemetrySerilogSinkOptions +{ + /// + /// Gets or sets a value indicating whether or not rendered log message + /// should be included on generated s. Default + /// value: . + /// + public bool IncludeRenderedMessage { get; set; } +} diff --git a/src/OpenTelemetry.Extensions.Serilog/README.md b/src/OpenTelemetry.Extensions.Serilog/README.md new file mode 100644 index 00000000000..2d0c837bfbb --- /dev/null +++ b/src/OpenTelemetry.Extensions.Serilog/README.md @@ -0,0 +1,36 @@ +# OpenTelemetry.Extensions.Serilog + +[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Extensions.Serilog.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.Serilog) +[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Extensions.Serilog.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.Serilog) + +This project contains a [Serilog](https://github.com/serilog/) +[sink](https://github.com/serilog/serilog/wiki/Configuration-Basics#sinks) for +writing log messages to OpenTelemetry. + +## Installation + +```shell +dotnet add package OpenTelemetry.Extensions.Serilog --prerelease +``` + +## Usage Example + +```csharp +// Step 1: Configure OpenTelemetryLoggerProvider... +var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .ConfigureResource(builder => builder.AddService("MyService")) + .AddConsoleExporter() + .Build(); + +// Step 2: Register OpenTelemetry sink with Serilog... +Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true) + .CreateLogger(); + +// Step 3: When application is shutdown flush all log messages and dispose provider... +Log.CloseAndFlush(); +``` + +## References + +* [OpenTelemetry Project](https://opentelemetry.io/) diff --git a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt index 782248e7e3a..e4585058956 100644 --- a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt @@ -85,8 +85,8 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~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.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 diff --git a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt index bf3ab6eedd6..8aa2a977d15 100644 --- a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,21 +1,71 @@ +Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions! +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void +OpenTelemetry.Logs.LoggerProviderBuilderExtensions +OpenTelemetry.Logs.LoggerProviderExtensions +OpenTelemetry.Logs.LogRecord.Attributes.get -> System.Collections.Generic.IReadOnlyList>? +OpenTelemetry.Logs.LogRecord.Attributes.set -> void +OpenTelemetry.Logs.LogRecord.Body.get -> string? +OpenTelemetry.Logs.LogRecord.Body.set -> void OpenTelemetry.Logs.LogRecord.CategoryName.set -> void OpenTelemetry.Logs.LogRecord.EventId.set -> void OpenTelemetry.Logs.LogRecord.Exception.set -> void +OpenTelemetry.Logs.LogRecord.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope? OpenTelemetry.Logs.LogRecord.LogLevel.set -> void +OpenTelemetry.Logs.LogRecord.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecord.Severity.set -> void OpenTelemetry.Logs.LogRecord.SpanId.set -> void OpenTelemetry.Logs.LogRecord.Timestamp.set -> void OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action? configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action! configureOptions) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action? configureOptions, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action! configureOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.Build(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProvider! provider, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderExtensions.ForceFlush(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool +static OpenTelemetry.Logs.LoggerProviderExtensions.Shutdown(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! +static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! ~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string @@ -28,8 +78,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.s OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOptions() -> void OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder! -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt index 782248e7e3a..e4585058956 100644 --- a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt @@ -85,8 +85,8 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~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.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 diff --git a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt index bf3ab6eedd6..8aa2a977d15 100644 --- a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -1,21 +1,71 @@ +Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions! +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void +OpenTelemetry.Logs.LoggerProviderBuilderExtensions +OpenTelemetry.Logs.LoggerProviderExtensions +OpenTelemetry.Logs.LogRecord.Attributes.get -> System.Collections.Generic.IReadOnlyList>? +OpenTelemetry.Logs.LogRecord.Attributes.set -> void +OpenTelemetry.Logs.LogRecord.Body.get -> string? +OpenTelemetry.Logs.LogRecord.Body.set -> void OpenTelemetry.Logs.LogRecord.CategoryName.set -> void OpenTelemetry.Logs.LogRecord.EventId.set -> void OpenTelemetry.Logs.LogRecord.Exception.set -> void +OpenTelemetry.Logs.LogRecord.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope? OpenTelemetry.Logs.LogRecord.LogLevel.set -> void +OpenTelemetry.Logs.LogRecord.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecord.Severity.set -> void OpenTelemetry.Logs.LogRecord.SpanId.set -> void OpenTelemetry.Logs.LogRecord.Timestamp.set -> void OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action? configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action! configureOptions) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action? configureOptions, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action! configureOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.Build(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProvider! provider, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderExtensions.ForceFlush(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool +static OpenTelemetry.Logs.LoggerProviderExtensions.Shutdown(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! +static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! ~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string @@ -28,8 +78,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.s OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOptions() -> void OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder! -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt index 782248e7e3a..e4585058956 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt @@ -85,8 +85,8 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~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.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 diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index bf3ab6eedd6..8aa2a977d15 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,21 +1,71 @@ +Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions! +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void +OpenTelemetry.Logs.LoggerProviderBuilderExtensions +OpenTelemetry.Logs.LoggerProviderExtensions +OpenTelemetry.Logs.LogRecord.Attributes.get -> System.Collections.Generic.IReadOnlyList>? +OpenTelemetry.Logs.LogRecord.Attributes.set -> void +OpenTelemetry.Logs.LogRecord.Body.get -> string? +OpenTelemetry.Logs.LogRecord.Body.set -> void OpenTelemetry.Logs.LogRecord.CategoryName.set -> void OpenTelemetry.Logs.LogRecord.EventId.set -> void OpenTelemetry.Logs.LogRecord.Exception.set -> void +OpenTelemetry.Logs.LogRecord.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope? OpenTelemetry.Logs.LogRecord.LogLevel.set -> void +OpenTelemetry.Logs.LogRecord.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecord.Severity.set -> void OpenTelemetry.Logs.LogRecord.SpanId.set -> void OpenTelemetry.Logs.LogRecord.Timestamp.set -> void OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action? configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action! configureOptions) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action? configureOptions, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action! configureOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.Build(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProvider! provider, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderExtensions.ForceFlush(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool +static OpenTelemetry.Logs.LoggerProviderExtensions.Shutdown(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! +static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! ~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string @@ -28,8 +78,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.s OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOptions() -> void OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder! -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt index 782248e7e3a..e4585058956 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt @@ -85,8 +85,8 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~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.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 diff --git a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt index bf3ab6eedd6..8aa2a977d15 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -1,21 +1,71 @@ +Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions +OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions! +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType +OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void +OpenTelemetry.Logs.LoggerProviderBuilderExtensions +OpenTelemetry.Logs.LoggerProviderExtensions +OpenTelemetry.Logs.LogRecord.Attributes.get -> System.Collections.Generic.IReadOnlyList>? +OpenTelemetry.Logs.LogRecord.Attributes.set -> void +OpenTelemetry.Logs.LogRecord.Body.get -> string? +OpenTelemetry.Logs.LogRecord.Body.set -> void OpenTelemetry.Logs.LogRecord.CategoryName.set -> void OpenTelemetry.Logs.LogRecord.EventId.set -> void OpenTelemetry.Logs.LogRecord.Exception.set -> void +OpenTelemetry.Logs.LogRecord.InstrumentationScope.get -> OpenTelemetry.InstrumentationScope? OpenTelemetry.Logs.LogRecord.LogLevel.set -> void +OpenTelemetry.Logs.LogRecord.Severity.get -> OpenTelemetry.Logs.LogRecordSeverity? +OpenTelemetry.Logs.LogRecord.Severity.set -> void OpenTelemetry.Logs.LogRecord.SpanId.set -> void OpenTelemetry.Logs.LogRecord.Timestamp.set -> void OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool +OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.set -> void +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder +OpenTelemetry.Logs.OpenTelemetryLoggingBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.DependencyInjection.LoggerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action? configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action! configureOptions) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.LoggerProvider! loggerProvider, System.Action? configureOptions, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder! +static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action! configureOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggingBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.Build(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProvider! provider, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Logs.LoggerProvider! +static OpenTelemetry.Logs.LoggerProviderExtensions.ForceFlush(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool +static OpenTelemetry.Logs.LoggerProviderExtensions.Shutdown(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder! +static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! ~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string @@ -28,8 +78,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.s OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOptions() -> void OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder! -static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, System.Action! configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/ApiCompatBaseline.txt b/src/OpenTelemetry/ApiCompatBaseline.txt new file mode 100644 index 00000000000..c4972b127eb --- /dev/null +++ b/src/OpenTelemetry/ApiCompatBaseline.txt @@ -0,0 +1,3 @@ +Compat issues with assembly OpenTelemetry: +MembersMustExist : Member 'public Microsoft.Extensions.Logging.ILoggingBuilder Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(Microsoft.Extensions.Logging.ILoggingBuilder, System.Action)' does not exist in the implementation but it does exist in the contract. +Total Issues: 1 diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index a284a1bedc5..153f5177913 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased-Logs + +* Added `LoggerProvider` API from the OpenTelemetry specification + ([#3707](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3707)) + ## Unreleased * Use binary search for histograms with 50 or more supplied boundaries. diff --git a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderServiceCollectionHelper.cs b/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs similarity index 63% rename from src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderServiceCollectionHelper.cs rename to src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs index e53f412828d..d3f020a180f 100644 --- a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderServiceCollectionHelper.cs +++ b/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,13 +20,14 @@ using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; -namespace OpenTelemetry.Metrics; +namespace OpenTelemetry; -internal static class MeterProviderBuilderServiceCollectionHelper +internal static class ProviderBuilderServiceCollectionCallbackHelper + where TState : ProviderBuilderState { - internal static IServiceCollection RegisterConfigureBuilderCallback( + public static IServiceCollection RegisterConfigureBuilderCallback( IServiceCollection services, - Action configure) + Action configure) { Debug.Assert(configure != null, "configure was null"); @@ -35,24 +36,25 @@ internal static IServiceCollection RegisterConfigureBuilderCallback( (sp, state) => configure!(sp, state.Builder)); } - internal static IServiceCollection RegisterConfigureStateCallback( + public static IServiceCollection RegisterConfigureStateCallback( IServiceCollection services, - Action configure) + Action configure) { Debug.Assert(services != null, "services was null"); Debug.Assert(configure != null, "configure was null"); - return services.AddSingleton(new ConfigureMeterProviderBuilderStateCallbackRegistration(configure!)); + return services.AddSingleton( + new ConfigureProviderBuilderStateCallbackRegistration(configure!)); } - internal static void InvokeRegisteredConfigureStateCallbacks( + public static void InvokeRegisteredConfigureStateCallbacks( IServiceProvider serviceProvider, - MeterProviderBuilderState state) + TState state) { Debug.Assert(serviceProvider != null, "serviceProvider was null"); Debug.Assert(state != null, "state was null"); - var callbackRegistrations = serviceProvider.GetServices(); + var callbackRegistrations = serviceProvider.GetServices(); foreach (var callbackRegistration in callbackRegistrations) { @@ -60,17 +62,17 @@ internal static void InvokeRegisteredConfigureStateCallbacks( } } - private sealed class ConfigureMeterProviderBuilderStateCallbackRegistration + private sealed class ConfigureProviderBuilderStateCallbackRegistration { - private readonly Action configure; + private readonly Action configure; - public ConfigureMeterProviderBuilderStateCallbackRegistration( - Action configure) + public ConfigureProviderBuilderStateCallbackRegistration( + Action configure) { this.configure = configure; } - public void Configure(IServiceProvider serviceProvider, MeterProviderBuilderState state) + public void Configure(IServiceProvider serviceProvider, TState state) { Debug.Assert(serviceProvider != null, "serviceProvider was null"); Debug.Assert(state != null, "state was null"); diff --git a/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs b/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs new file mode 100644 index 00000000000..7fb6d96adf3 --- /dev/null +++ b/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs @@ -0,0 +1,94 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using OpenTelemetry.Resources; + +namespace OpenTelemetry; + +internal abstract class ProviderBuilderState +{ + protected ProviderBuilderState( + IServiceProvider serviceProvider, + TProvider provider) + { + Debug.Assert(serviceProvider != null, "serviceProvider was null"); + Debug.Assert(provider != null, "provider was null"); + + this.ServiceProvider = serviceProvider!; + this.Provider = provider; + } + + public IServiceProvider ServiceProvider { get; } + + public abstract TBuilder Builder { get; } + + public TProvider Provider { get; } + + public List Instrumentation { get; } = new(); + + public ResourceBuilder? ResourceBuilder { get; protected set; } + + public void AddInstrumentation( + string instrumentationName, + string instrumentationVersion, + object instrumentation) + { + Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace"); + Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace"); + Debug.Assert(instrumentation != null, "instrumentation was null"); + + this.Instrumentation.Add( + new InstrumentationRegistration( + instrumentationName, + instrumentationVersion, + instrumentation!)); + } + + public void ConfigureResource(Action configure) + { + Debug.Assert(configure != null, "configure was null"); + + var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault(); + + configure!(resourceBuilder); + } + + public void SetResourceBuilder(ResourceBuilder resourceBuilder) + { + Debug.Assert(resourceBuilder != null, "resourceBuilder was null"); + + this.ResourceBuilder = resourceBuilder; + } + + internal readonly struct InstrumentationRegistration + { + public readonly string Name; + public readonly string Version; + public readonly object Instance; + + internal InstrumentationRegistration(string name, string version, object instance) + { + this.Name = name; + this.Version = version; + this.Instance = instance; + } + } +} diff --git a/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs b/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs index f9f6b6f2ed8..ee30b7fc68b 100644 --- a/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs +++ b/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs @@ -152,6 +152,15 @@ public void MeterProviderException(string methodName, Exception ex) } } + [NonEvent] + public void LoggerProviderException(string methodName, Exception ex) + { + if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + this.LoggerProviderException(methodName, ex.ToInvariantString()); + } + } + [NonEvent] public void MissingPermissionsToReadEnvironmentVariable(SecurityException ex) { @@ -180,6 +189,15 @@ public void DroppedExportProcessorItems(string exportProcessorName, string expor } } + [NonEvent] + public void LoggerParseStateException(Exception exception) + { + if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + this.LoggerParseStateException(typeof(TState).FullName, exception.ToInvariantString()); + } + } + [Event(1, Message = "Span processor queue size reached maximum. Throttling spans.", Level = EventLevel.Warning)] public void SpanProcessorQueueIsExhausted() { @@ -396,16 +414,22 @@ public void ProcessorForceFlushInvoked(string processorType, bool result) this.WriteEvent(43, processorType, result); } - [Event(44, Message = "OpenTelemetryLoggerProvider event: '{0}'", Level = EventLevel.Verbose)] - public void OpenTelemetryLoggerProviderEvent(string message) + [Event(44, Message = "LoggerProviderSdk event: '{0}'", Level = EventLevel.Verbose)] + public void LoggerProviderSdkEvent(string message) { this.WriteEvent(44, message); } - [Event(45, Message = "ForceFlush invoked for OpenTelemetryLoggerProvider with timeoutMilliseconds = '{0}'.", Level = EventLevel.Verbose)] - public void OpenTelemetryLoggerProviderForceFlushInvoked(int timeoutMilliseconds) + [Event(45, Message = "Exception thrown parsing log state of type '{0}'. Exception: '{1}'", Level = EventLevel.Error)] + public void LoggerParseStateException(string type, string error) + { + this.WriteEvent(45, type, error); + } + + [Event(46, Message = "Unknown error in LoggerProvider '{0}': '{1}'.", Level = EventLevel.Error)] + public void LoggerProviderException(string methodName, string ex) { - this.WriteEvent(45, timeoutMilliseconds); + this.WriteEvent(46, methodName, ex); } #if DEBUG diff --git a/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs b/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs new file mode 100644 index 00000000000..ea23f314e7c --- /dev/null +++ b/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs @@ -0,0 +1,75 @@ +// +// 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.Logs +{ + /// + /// Batch log processor options. OTEL_BLRP_MAX_QUEUE_SIZE, + /// OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_EXPORT_TIMEOUT, + /// OTEL_BLRP_SCHEDULE_DELAY environment variables are parsed during object + /// construction. + /// + /// + /// Notes: + /// + /// The constructor throws if it fails + /// to parse any of the supported environment variables. + /// The environment variable keys are currently experimental and + /// subject to change. See: OpenTelemetry + /// Environment Variable Specification - Batch LogRecord Processor. + /// + /// + /// + public class BatchExportLogRecordProcessorOptions : BatchExportProcessorOptions + { + internal const string MaxQueueSizeEnvVarKey = "OTEL_BLRP_MAX_QUEUE_SIZE"; + + internal const string MaxExportBatchSizeEnvVarKey = "OTEL_BLRP_MAX_EXPORT_BATCH_SIZE"; + + internal const string ExporterTimeoutEnvVarKey = "OTEL_BLRP_EXPORT_TIMEOUT"; + + internal const string ScheduledDelayEnvVarKey = "OTEL_BLRP_SCHEDULE_DELAY"; + + public BatchExportLogRecordProcessorOptions() + { + int value; + + if (EnvironmentVariableHelper.LoadNumeric(ExporterTimeoutEnvVarKey, out value)) + { + this.ExporterTimeoutMilliseconds = value; + } + + if (EnvironmentVariableHelper.LoadNumeric(MaxExportBatchSizeEnvVarKey, out value)) + { + this.MaxExportBatchSize = value; + } + + if (EnvironmentVariableHelper.LoadNumeric(MaxQueueSizeEnvVarKey, out value)) + { + this.MaxQueueSize = value; + } + + if (EnvironmentVariableHelper.LoadNumeric(ScheduledDelayEnvVarKey, out value)) + { + this.ScheduledDelayMilliseconds = value; + } + } + } +} diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs new file mode 100644 index 00000000000..4171040f021 --- /dev/null +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs @@ -0,0 +1,295 @@ +// +// 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. +// + +#nullable enable + +using System; +using Microsoft.Extensions.DependencyInjection; +using OpenTelemetry.Resources; + +namespace OpenTelemetry.Logs; + +/// +/// Contains extension methods for the class. +/// +public static class LoggerProviderBuilderExtensions +{ + /// + /// Sets the from which the Resource associated with + /// this provider is built from. Overwrites currently set ResourceBuilder. + /// You should usually use instead + /// (call if desired). + /// + /// . + /// from which Resource will be built. + /// Returns for chaining. + public static LoggerProviderBuilder SetResourceBuilder(this LoggerProviderBuilder loggerProviderBuilder, ResourceBuilder resourceBuilder) + { + ResolveSdkBuilder(loggerProviderBuilder)?.SetResourceBuilder(resourceBuilder); + + return loggerProviderBuilder; + } + + /// + /// Modify the from which the Resource associated with + /// this provider is built from in-place. + /// + /// . + /// An action which modifies the provided in-place. + /// Returns for chaining. + public static LoggerProviderBuilder ConfigureResource(this LoggerProviderBuilder loggerProviderBuilder, Action configure) + { + ResolveSdkBuilder(loggerProviderBuilder)?.ConfigureResource(configure); + + return loggerProviderBuilder; + } + + /// + /// Adds a processor to the provider. + /// + /// . + /// Activity processor to add. + /// Returns for chaining. + public static LoggerProviderBuilder AddProcessor(this LoggerProviderBuilder loggerProviderBuilder, BaseProcessor processor) + { + ResolveSdkBuilder(loggerProviderBuilder)?.AddProcessor(processor); + + return loggerProviderBuilder; + } + + /// + /// Adds a processor to the provider which will be retrieved using dependency injection. + /// + /// + /// Note: The type specified by will be + /// registered as a singleton service into application services. + /// + /// Processor type. + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddProcessor(this LoggerProviderBuilder loggerProviderBuilder) + where T : BaseProcessor + { + ResolveSdkBuilder(loggerProviderBuilder)?.AddProcessor(); + + return loggerProviderBuilder; + } + + /// + /// Adds an exporter to the provider. + /// + /// . + /// . + /// LogRecord exporter to add. + /// Returns for chaining. + public static LoggerProviderBuilder AddExporter( + this LoggerProviderBuilder loggerProviderBuilder, + ExportProcessorType exportProcessorType, + BaseExporter exporter) + => AddExporter(loggerProviderBuilder, exportProcessorType, exporter, name: null, configure: null); + + /// + /// Adds an exporter to the provider. + /// + /// . + /// . + /// LogRecord exporter to add. + /// + /// Returns for chaining. + public static LoggerProviderBuilder AddExporter( + this LoggerProviderBuilder loggerProviderBuilder, + ExportProcessorType exportProcessorType, + BaseExporter exporter, + Action configure) + => AddExporter(loggerProviderBuilder, exportProcessorType, exporter, name: null, configure); + + /// + /// Adds an exporter to the provider. + /// + /// . + /// . + /// LogRecord exporter to add. + /// Name which is used when retrieving options. + /// + /// Returns for chaining. + public static LoggerProviderBuilder AddExporter( + this LoggerProviderBuilder loggerProviderBuilder, + ExportProcessorType exportProcessorType, + BaseExporter exporter, + string? name, + Action? configure) + { + ResolveSdkBuilder(loggerProviderBuilder)?.AddExporter(exportProcessorType, exporter, name, configure); + + return loggerProviderBuilder; + } + + /// + /// Adds an exporter to the provider which will be retrieved using dependency injection. + /// + /// + /// Exporter type. + /// . + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddExporter( + this LoggerProviderBuilder loggerProviderBuilder, + ExportProcessorType exportProcessorType) + where T : BaseExporter + => AddExporter(loggerProviderBuilder, exportProcessorType, name: null, configure: null); + + /// + /// Adds an exporter to the provider which will be retrieved using dependency injection. + /// + /// + /// Exporter type. + /// . + /// . + /// + /// The supplied for chaining. + public static LoggerProviderBuilder AddExporter( + this LoggerProviderBuilder loggerProviderBuilder, + ExportProcessorType exportProcessorType, + Action configure) + where T : BaseExporter + => AddExporter(loggerProviderBuilder, exportProcessorType, name: null, configure); + + /// + /// Adds an exporter to the provider which will be retrieved using dependency injection. + /// + /// + /// Note: The type specified by will be + /// registered as a singleton service into application services. + /// + /// Exporter type. + /// . + /// . + /// Name which is used when retrieving options. + /// Callback action to configure . Only invoked when is . + /// The supplied for chaining. + public static LoggerProviderBuilder AddExporter( + this LoggerProviderBuilder loggerProviderBuilder, + ExportProcessorType exportProcessorType, + string? name, + Action? configure) + where T : BaseExporter + { + ResolveSdkBuilder(loggerProviderBuilder)?.AddExporter(exportProcessorType, name, configure); + + return loggerProviderBuilder; + } + + /// + /// Adds instrumentation to the provider. + /// + /// + /// Note: The type specified by will be + /// registered as a singleton service into application services. + /// + /// Instrumentation type. + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddInstrumentation(this LoggerProviderBuilder loggerProviderBuilder) + where T : class + { + ResolveSdkBuilder(loggerProviderBuilder)?.AddInstrumentation(); + + return loggerProviderBuilder; + } + + /// + /// Adds instrumentation to the provider. + /// + /// Instrumentation type. + /// . + /// Function that builds instrumentation. + /// The supplied for chaining. + public static LoggerProviderBuilder AddInstrumentation( + this LoggerProviderBuilder loggerProviderBuilder, + Func instrumentationFactory) + where T : class + { + ResolveSdkBuilder(loggerProviderBuilder)?.AddInstrumentation(instrumentationFactory); + + return loggerProviderBuilder; + } + + /// + /// Register a callback action to configure the where tracing services are configured. + /// + /// + /// Note: Tracing services are only available during the application + /// configuration phase. + /// + /// . + /// Configuration callback. + /// The supplied for chaining. + public static LoggerProviderBuilder ConfigureServices( + this LoggerProviderBuilder loggerProviderBuilder, + Action configure) + { + ResolveSdkBuilder(loggerProviderBuilder)?.ConfigureServices(configure); + + return loggerProviderBuilder; + } + + /// + /// Register a callback action to configure the once the application is available. + /// + /// . + /// Configuration callback. + /// The supplied for chaining. + public static LoggerProviderBuilder ConfigureBuilder( + this LoggerProviderBuilder loggerProviderBuilder, + Action configure) + { + ResolveSdkBuilder(loggerProviderBuilder)?.ConfigureBuilder(configure); + + return loggerProviderBuilder; + } + + /// + /// Run the given actions to initialize the . + /// + /// . + /// . + public static LoggerProvider Build(this LoggerProviderBuilder loggerProviderBuilder) + { + var provider = ResolveSdkBuilder(loggerProviderBuilder)?.Build(); + + return provider ?? new NoopLoggerProvider(); + } + + private static LoggerProviderBuilderSdk? ResolveSdkBuilder(LoggerProviderBuilder loggerProviderBuilder) + { + if (loggerProviderBuilder is LoggerProviderBuilderSdk loggerProviderBuilderSdk) + { + return loggerProviderBuilderSdk; + } + else if (loggerProviderBuilder is OpenTelemetryLoggingBuilder openTelemetryLoggingBuilder) + { + return openTelemetryLoggingBuilder.InnerBuiler; + } + + return null; + } +} diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs new file mode 100644 index 00000000000..03879a8066c --- /dev/null +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs @@ -0,0 +1,273 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Diagnostics; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using OpenTelemetry.Internal; +using OpenTelemetry.Resources; + +using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper< + OpenTelemetry.Logs.LoggerProviderBuilderSdk, + OpenTelemetry.Logs.LoggerProviderSdk, + OpenTelemetry.Logs.LoggerProviderBuilderState>; + +namespace OpenTelemetry.Logs; + +internal sealed class LoggerProviderBuilderSdk : LoggerProviderBuilder, IDeferredLoggerProviderBuilder +{ + internal readonly LoggerProviderBuilderState? State; + + private readonly bool ownsServices; + private IServiceCollection? services; + + // This ctor is for a builder created from LoggerProviderBuilderState which + // happens after the service provider has been created. + public LoggerProviderBuilderSdk(LoggerProviderBuilderState state) + { + Debug.Assert(state != null, "state was null"); + + this.State = state; + } + + // This ctor is for ILoggingBuilder.AddOpenTelemetry scenario where the + // builder is bound to an external service collection. + public LoggerProviderBuilderSdk(IServiceCollection services) + { + Debug.Assert(services != null, "services was null"); + + services.AddOptions(); + services.TryAddSingleton(sp => new LoggerProviderSdk(sp, ownsServiceProvider: false)); + + this.services = services; + this.ownsServices = false; + } + + // This ctor is for Sdk.CreateLoggerProviderBuilder where the builder + // owns its services and service provider. + public LoggerProviderBuilderSdk() + { + var services = new ServiceCollection(); + + services.AddOptions(); + + this.services = services; + this.ownsServices = true; + } + + /// + LoggerProviderBuilder IDeferredLoggerProviderBuilder.Configure( + Action configure) + => this.ConfigureBuilder(configure); + + public LoggerProviderBuilder AddExporter(ExportProcessorType exportProcessorType, string? name, Action? configure) + where T : BaseExporter + { + this.TryAddSingleton(); + this.ConfigureState((sp, state) + => state.AddProcessor( + BuildExportProcessor(state.ServiceProvider, exportProcessorType, sp.GetRequiredService(), name, configure))); + + return this; + } + + public LoggerProviderBuilder AddExporter(ExportProcessorType exportProcessorType, BaseExporter exporter, string? name, Action? configure) + { + Guard.ThrowIfNull(exporter); + + this.ConfigureState((sp, state) + => state.AddProcessor( + BuildExportProcessor(state.ServiceProvider, exportProcessorType, exporter, name, configure))); + + return this; + } + + public LoggerProviderBuilder AddInstrumentation( + Func instrumentationFactory) + where T : class + { + Guard.ThrowIfNull(instrumentationFactory); + + this.ConfigureState((sp, state) + => state.AddInstrumentation( + typeof(T).Name, + "semver:" + typeof(T).Assembly.GetName().Version, + instrumentationFactory(sp, state.Provider))); + + return this; + } + + public LoggerProviderBuilder AddInstrumentation() + where T : class + { + this.TryAddSingleton(); + this.AddInstrumentation((sp, provider) => sp.GetRequiredService()); + + return this; + } + + public LoggerProviderBuilder AddProcessor(BaseProcessor processor) + { + Guard.ThrowIfNull(processor); + + return this.ConfigureState((sp, state) => state.AddProcessor(processor)); + } + + public LoggerProviderBuilder AddProcessor() + where T : BaseProcessor + { + this.TryAddSingleton(); + this.ConfigureState((sp, state) => state.AddProcessor(sp.GetRequiredService())); + + return this; + } + + public LoggerProviderBuilder ConfigureBuilder(Action configure) + { + Guard.ThrowIfNull(configure); + + if (this.State != null) + { + configure(this.State.ServiceProvider, this); + } + else + { + this.ConfigureServices(services + => CallbackHelper.RegisterConfigureBuilderCallback(services, configure)); + } + + return this; + } + + public LoggerProviderBuilder ConfigureResource(Action configure) + { + Guard.ThrowIfNull(configure); + + return this.ConfigureState((sp, state) => state.ConfigureResource(configure)); + } + + public LoggerProviderBuilder ConfigureServices(Action configure) + { + Guard.ThrowIfNull(configure); + + var services = this.services; + + if (services == null) + { + throw new NotSupportedException("Services cannot be configured after ServiceProvider has been created."); + } + + configure(services); + + return this; + } + + public LoggerProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder) + { + Guard.ThrowIfNull(resourceBuilder); + + return this.ConfigureState((sp, state) => state.SetResourceBuilder(resourceBuilder)); + } + + public LoggerProvider Build() + { + if (!this.ownsServices || this.State != null) + { + throw new NotSupportedException("Build cannot be called directly on LoggerProviderBuilder tied to external services."); + } + + var services = this.services; + + if (services == null) + { + throw new NotSupportedException("LoggerProviderBuilder build method cannot be called multiple times."); + } + + this.services = null; + +#if DEBUG + bool validateScopes = true; +#else + bool validateScopes = false; +#endif + var serviceProvider = services.BuildServiceProvider(validateScopes); + + return new LoggerProviderSdk(serviceProvider, ownsServiceProvider: true); + } + + private static BaseProcessor BuildExportProcessor( + IServiceProvider serviceProvider, + ExportProcessorType exportProcessorType, + BaseExporter exporter, + string? name, + Action? configure) + { + name ??= Options.DefaultName; + + switch (exportProcessorType) + { + case ExportProcessorType.Simple: + return new SimpleLogRecordExportProcessor(exporter); + case ExportProcessorType.Batch: + var options = serviceProvider.GetRequiredService>().Get(name); + + options.ExportProcessorType = ExportProcessorType.Batch; + + configure?.Invoke(options); + + var batchOptions = options.BatchExportProcessorOptions; + + return new BatchLogRecordExportProcessor( + exporter, + batchOptions.MaxQueueSize, + batchOptions.ScheduledDelayMilliseconds, + batchOptions.ExporterTimeoutMilliseconds, + batchOptions.MaxExportBatchSize); + default: + throw new NotSupportedException($"ExportProcessorType '{exportProcessorType}' is not supported."); + } + } + + private LoggerProviderBuilder ConfigureState(Action configure) + { + Debug.Assert(configure != null, "configure was null"); + + if (this.State != null) + { + configure!(this.State.ServiceProvider, this.State); + } + else + { + this.ConfigureServices(services + => CallbackHelper.RegisterConfigureStateCallback(services, configure!)); + } + + return this; + } + + private void TryAddSingleton() + where T : class + { + var services = this.services; + + services?.TryAddSingleton(); + } +} + diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderServiceCollectionExtensions.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderServiceCollectionExtensions.cs new file mode 100644 index 00000000000..6f3c40e5763 --- /dev/null +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderServiceCollectionExtensions.cs @@ -0,0 +1,81 @@ +// +// 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. +// + +#nullable enable + +using System; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Internal; +using OpenTelemetry.Logs; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods for setting up OpenTelemetry logging services in an . +/// +public static class LoggerProviderBuilderServiceCollectionExtensions +{ + /// + /// Configures OpenTelemetry logging services in the supplied . + /// + /// + /// Notes: + /// + /// A will NOT be created automatically + /// using this method. Either use the + /// extension or access the through the + /// application to begin collecting + /// logs. + /// This is safe to be called multiple times and by library authors. + /// Only a single will be created for a given + /// . + /// + /// + /// The to add + /// services to. + /// The so that additional calls + /// can be chained. + public static IServiceCollection ConfigureOpenTelemetryLogging(this IServiceCollection services) + => ConfigureOpenTelemetryLogging(services, configure: null); + + /// + /// Configures OpenTelemetry logging services in the supplied . + /// + /// + /// The to add services to. + /// Callback action to configure the . + /// The so that additional calls can be chained. + public static IServiceCollection ConfigureOpenTelemetryLogging(this IServiceCollection services, Action? configure) + { + Guard.ThrowIfNull(services); + + // Accessing Sdk class is just to trigger its static ctor, + // which sets default Propagators and default Activity Id format + _ = Sdk.SuppressInstrumentation; + + // Note: We need to create a builder even if there is no configure + // because the builder will register services needed by + // LoggerProviderSdk in the service collection + var builder = new LoggerProviderBuilderSdk(services); + + configure?.Invoke(builder); + + return services; + } +} diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs new file mode 100644 index 00000000000..fb175d6d338 --- /dev/null +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs @@ -0,0 +1,50 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace OpenTelemetry.Logs; + +/// +/// Stores state used to build a . +/// +internal sealed class LoggerProviderBuilderState : ProviderBuilderState +{ + private LoggerProviderBuilderSdk? builder; + + public LoggerProviderBuilderState( + IServiceProvider serviceProvider, + LoggerProviderSdk provider) + : base(serviceProvider, provider) + { + } + + public override LoggerProviderBuilderSdk Builder + => this.builder ??= new LoggerProviderBuilderSdk(this); + + public List> Processors { get; } = new(); + + public void AddProcessor(BaseProcessor processor) + { + Debug.Assert(processor != null, "processor was null"); + + this.Processors.Add(processor!); + } +} diff --git a/src/OpenTelemetry/Logs/ExportLogRecordProcessorOptions.cs b/src/OpenTelemetry/Logs/ExportLogRecordProcessorOptions.cs new file mode 100644 index 00000000000..0915997de27 --- /dev/null +++ b/src/OpenTelemetry/Logs/ExportLogRecordProcessorOptions.cs @@ -0,0 +1,45 @@ +// +// 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. +// + +#nullable enable + +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs; + +public class ExportLogRecordProcessorOptions +{ + private BatchExportLogRecordProcessorOptions? batchExportProcessorOptions; + + /// + /// Gets or sets the export processor type to be used. The default value is . + /// + public ExportProcessorType ExportProcessorType { get; set; } + + /// + /// Gets or sets the batch export options. Ignored unless is . + /// + public BatchExportLogRecordProcessorOptions BatchExportProcessorOptions + { + get => this.batchExportProcessorOptions ??= new(); + set + { + Guard.ThrowIfNull(value); + + this.batchExportProcessorOptions = value; + } + } +} diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLogger.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLogger.cs new file mode 100644 index 00000000000..c5107dec35e --- /dev/null +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLogger.cs @@ -0,0 +1,210 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using Microsoft.Extensions.Logging; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + internal sealed class OpenTelemetryLogger : ILogger + { + private static readonly InstrumentationScope InstrumentationScope = new("OpenTelemetry") + { + Version = $"semver:{typeof(OpenTelemetryLogger).Assembly.GetName().Version}", + }; + + private readonly string categoryName; + private readonly OpenTelemetryLoggerProvider iloggerProvider; + private readonly LoggerProviderSdk? otelLoggerProvider; + + internal OpenTelemetryLogger(string categoryName, OpenTelemetryLoggerProvider provider) + { + Guard.ThrowIfNull(categoryName); + Guard.ThrowIfNull(provider); + + this.categoryName = categoryName; + this.iloggerProvider = provider; + this.otelLoggerProvider = provider.Provider as LoggerProviderSdk; + } + + internal IExternalScopeProvider? ScopeProvider { get; set; } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + if (!this.IsEnabled(logLevel) + || Sdk.SuppressInstrumentation) + { + return; + } + + var iloggerProvider = this.iloggerProvider; + var processor = this.otelLoggerProvider?.Processor; + if (processor != null) + { + var activity = Activity.Current; + + var pool = this.otelLoggerProvider!.LogRecordPool; + + var record = pool.Rent(); + + ref LogRecord.LogRecordILoggerData iloggerData = ref record.ILoggerData; + + iloggerData.TraceState = iloggerProvider.IncludeTraceState && activity != null + ? activity.TraceStateString + : null; + iloggerData.CategoryName = this.categoryName; + iloggerData.EventId = eventId; + iloggerData.Exception = exception; + + ref LogRecordData data = ref record.Data; + + data.TimestampBacking = DateTime.UtcNow; + data.Severity = (LogRecordSeverity)logLevel; + + LogRecordData.SetActivityContext(ref data, activity); + + record.InstrumentationScope = InstrumentationScope; + + var attributes = record.Attributes = iloggerProvider.IncludeState + ? ProcessState(record, state, iloggerProvider.ParseStateValues) + : null; + + if (attributes != null && attributes.Count > 0) + { + iloggerData.State = null; + + var lastAttribute = attributes[attributes.Count - 1]; + data.Body = lastAttribute.Key == "{OriginalFormat}" + ? lastAttribute.Value as string + : null; + } + else + { + iloggerData.State = !iloggerProvider.ParseStateValues ? state : null; + + data.Body = null; + } + + if (data.Body == null) + { + iloggerData.FormattedMessage = data.Body = formatter?.Invoke(state, exception); + } + else + { + iloggerData.FormattedMessage = iloggerProvider.IncludeFormattedMessage ? formatter?.Invoke(state, exception) : null; + } + + record.ScopeProvider = iloggerProvider.IncludeScopes ? this.ScopeProvider : null; + processor.OnEnd(record); + record.ScopeProvider = null; + + // Attempt to return the LogRecord to the pool. This will no-op + // if a batch exporter has added a reference. + pool.Return(record); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsEnabled(LogLevel logLevel) + { + return logLevel != LogLevel.None; + } + + public IDisposable BeginScope(TState state) => this.ScopeProvider?.Push(state) ?? NullScope.Instance; + + private static IReadOnlyList>? ProcessState(LogRecord logRecord, TState state, bool parseStateValues) + { + /* TODO: Enable this if/when LogRecordAttributeList becomes public. + if (state is LogRecordAttributeList logRecordAttributes) + { + logRecordAttributes.ApplyToLogRecord(logRecord); + return logRecord.AttributeStorage!; + } + else*/ + if (state is IReadOnlyList> stateList) + { + return stateList; + } + else if (state is IEnumerable> stateValues) + { + var attributeStorage = logRecord.AttributeStorage; + if (attributeStorage == null) + { + return logRecord.AttributeStorage = new List>(stateValues); + } + else + { + attributeStorage.AddRange(stateValues); + return attributeStorage; + } + } + else + { + if (!parseStateValues || state is null) + { + return null; + } + + try + { + PropertyDescriptorCollection itemProperties = TypeDescriptor.GetProperties(state); + + var attributeStorage = logRecord.AttributeStorage ??= new List>(itemProperties.Count); + + foreach (PropertyDescriptor? itemProperty in itemProperties) + { + if (itemProperty == null) + { + continue; + } + + object? value = itemProperty.GetValue(state); + if (value == null) + { + continue; + } + + attributeStorage.Add(new KeyValuePair(itemProperty.Name, value)); + } + + return attributeStorage; + } + catch (Exception parseException) + { + OpenTelemetrySdkEventSource.Log.LoggerParseStateException(parseException); + + return Array.Empty>(); + } + } + } + + private sealed class NullScope : IDisposable + { + public static NullScope Instance { get; } = new(); + + public void Dispose() + { + } + } + } +} diff --git a/src/OpenTelemetry/Logs/Options/OpenTelemetryLoggerOptions.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs similarity index 51% rename from src/OpenTelemetry/Logs/Options/OpenTelemetryLoggerOptions.cs rename to src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs index 022df5c1175..9028ffa3a57 100644 --- a/src/OpenTelemetry/Logs/Options/OpenTelemetryLoggerOptions.cs +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs @@ -18,65 +18,99 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.Extensions.Logging; using OpenTelemetry.Internal; using OpenTelemetry.Resources; namespace OpenTelemetry.Logs { /// - /// Contains OpenTelemetry logging options. + /// Contains options that apply to log messages written through the + /// OpenTelemetry . /// public class OpenTelemetryLoggerOptions { internal readonly List> Processors = new(); - internal ResourceBuilder ResourceBuilder = ResourceBuilder.CreateDefault(); + internal ResourceBuilder? ResourceBuilder; + + /// + /// Gets or sets a value indicating whether or not formatted log message + /// should be included on generated s. Default + /// value: . + /// + /// + /// Note: When set to a formatted log message + /// will not be included if a message template can be found. If a + /// message template is not found, a formatted log message is always + /// included. + /// + public bool IncludeFormattedMessage { get; set; } /// /// Gets or sets a value indicating whether or not log scopes should be /// included on generated s. Default value: - /// False. + /// . /// public bool IncludeScopes { get; set; } /// - /// Gets or sets a value indicating whether or not formatted log message - /// should be included on generated s. Default - /// value: False. + /// Gets or sets a value indicating whether or not log state should + /// be included on generated s. Default value: + /// . /// - public bool IncludeFormattedMessage { get; set; } + public bool IncludeState { get; set; } = true; + + /// + /// Gets or sets a value indicating whether or not the for the current should be included on generated s. Default value: . + /// + public bool IncludeTraceState { get; set; } /// /// Gets or sets a value indicating whether or not log state should be - /// parsed into on generated s. Default value: False. + /// parsed into on generated s. Default value: . /// /// - /// Note: When is set to + /// Parsing is only executed when the state logged does NOT + /// implement or where T is KeyValuePair<string, + /// object>. + /// When is set to will always be . + /// langword="null"/>. + /// /// public bool ParseStateValues { get; set; } /// - /// Adds processor to the options. + /// Adds a processor to the provider. /// - /// Log processor to add. - /// Returns for chaining. + /// LogRecord processor to add. + /// Returns for chaining. + [Obsolete("Use LoggerProviderBuilder instead of OpenTelemetryLoggerOptions to configure a LoggerProvider this method will be removed in a future version.")] public OpenTelemetryLoggerOptions AddProcessor(BaseProcessor processor) { Guard.ThrowIfNull(processor); this.Processors.Add(processor); - return this; } /// /// Sets the from which the Resource associated with /// this provider is built from. Overwrites currently set ResourceBuilder. + /// You should usually use instead + /// (call if desired). /// /// from which Resource will be built. - /// Returns for chaining. + /// Returns for chaining. + [Obsolete("Use LoggerProviderBuilder instead of OpenTelemetryLoggerOptions to configure a LoggerProvider this method will be removed in a future version.")] public OpenTelemetryLoggerOptions SetResourceBuilder(ResourceBuilder resourceBuilder) { Guard.ThrowIfNull(resourceBuilder); @@ -91,10 +125,12 @@ public OpenTelemetryLoggerOptions SetResourceBuilder(ResourceBuilder resourceBui /// /// An action which modifies the provided in-place. /// Returns for chaining. + [Obsolete("Use LoggerProviderBuilder instead of OpenTelemetryLoggerOptions to configure a LoggerProvider this method will be removed in a future version.")] public OpenTelemetryLoggerOptions ConfigureResource(Action configure) { - Guard.ThrowIfNull(configure, nameof(configure)); - configure(this.ResourceBuilder); + Guard.ThrowIfNull(configure); + + configure(this.ResourceBuilder ??= ResourceBuilder.CreateDefault()); return this; } } diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerProvider.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerProvider.cs new file mode 100644 index 00000000000..09399d562ad --- /dev/null +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerProvider.cs @@ -0,0 +1,170 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + /// + /// An implementation for exporting logs using OpenTelemetry. + /// + [ProviderAlias("OpenTelemetry")] + public class OpenTelemetryLoggerProvider : BaseProvider, ILoggerProvider, ISupportExternalScope + { + internal readonly LoggerProvider Provider; + private readonly bool ownsProvider; + private readonly Hashtable loggers = new(); + private bool disposed; + + static OpenTelemetryLoggerProvider() + { + // Accessing Sdk class is just to trigger its static ctor, + // which sets default Propagators and default Activity Id format + _ = Sdk.SuppressInstrumentation; + } + + /// + /// Initializes a new instance of the class. + /// + /// . + [Obsolete("Use the Sdk.CreateLoggerProviderBuilder method instead this ctor will be removed in a future version.")] + public OpenTelemetryLoggerProvider(IOptionsMonitor options) + { + Guard.ThrowIfNull(options); + + var currentOptions = options.CurrentValue; + + this.SetOptions(currentOptions); + + this.Provider = Sdk + .CreateLoggerProviderBuilder() + .ConfigureBuilder((sp, builder) => + { + if (currentOptions.ResourceBuilder != null) + { + builder.SetResourceBuilder(currentOptions.ResourceBuilder); + } + + foreach (var processor in currentOptions.Processors) + { + builder.AddProcessor(processor); + } + }) + .Build(); + + this.ownsProvider = true; + } + + internal OpenTelemetryLoggerProvider( + OpenTelemetryLoggerOptions options, + LoggerProvider loggerProvider, + bool disposeProvider) + { + Guard.ThrowIfNull(loggerProvider); + + this.SetOptions(options); + + this.Provider = loggerProvider; + this.ownsProvider = disposeProvider; + } + + internal bool IncludeFormattedMessage { get; private set; } + + internal bool IncludeScopes { get; private set; } + + internal bool IncludeState { get; private set; } + + internal bool IncludeTraceState { get; private set; } + + internal bool ParseStateValues { get; private set; } + + internal IExternalScopeProvider? ScopeProvider { get; private set; } + + /// + void ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider) + { + this.ScopeProvider = scopeProvider; + + lock (this.loggers) + { + foreach (DictionaryEntry entry in this.loggers) + { + if (entry.Value is OpenTelemetryLogger logger) + { + logger.ScopeProvider = scopeProvider; + } + } + } + } + + /// + public ILogger CreateLogger(string categoryName) + { + if (this.loggers[categoryName] is not OpenTelemetryLogger logger) + { + lock (this.loggers) + { + logger = (this.loggers[categoryName] as OpenTelemetryLogger)!; + if (logger == null) + { + logger = new OpenTelemetryLogger(categoryName, this) + { + ScopeProvider = this.ScopeProvider, + }; + + this.loggers[categoryName] = logger; + } + } + } + + return logger; + } + + /// + protected override void Dispose(bool disposing) + { + if (!this.disposed) + { + if (disposing) + { + if (this.ownsProvider) + { + this.Provider.Dispose(); + } + } + + this.disposed = true; + } + } + + private void SetOptions(OpenTelemetryLoggerOptions options) + { + Guard.ThrowIfNull(options); + + this.IncludeFormattedMessage = options.IncludeFormattedMessage; + this.IncludeScopes = options.IncludeScopes; + this.IncludeState = options.IncludeState; + this.IncludeTraceState = options.IncludeTraceState; + this.ParseStateValues = options.ParseStateValues; + } + } +} diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingBuilder.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingBuilder.cs new file mode 100644 index 00000000000..69f39cc74f0 --- /dev/null +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingBuilder.cs @@ -0,0 +1,42 @@ +// +// 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. +// + +#nullable enable + +using System.Diagnostics; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace OpenTelemetry.Logs; + +/// +/// An implementation that exposes methods for configuring OpenTelemetry. +/// +public sealed class OpenTelemetryLoggingBuilder : LoggerProviderBuilder, ILoggingBuilder +{ + internal OpenTelemetryLoggingBuilder(IServiceCollection services) + { + Debug.Assert(services != null, "services was null"); + + this.InnerBuiler = new LoggerProviderBuilderSdk(services!); + this.Services = services!; + } + + /// + public IServiceCollection Services { get; } + + internal LoggerProviderBuilderSdk InnerBuiler { get; } +} diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs new file mode 100644 index 00000000000..e6658b71133 --- /dev/null +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs @@ -0,0 +1,241 @@ +// +// 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. +// + +#nullable enable + +using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Configuration; +using Microsoft.Extensions.Options; +using OpenTelemetry.Internal; +using OpenTelemetry.Logs; + +namespace Microsoft.Extensions.Logging +{ + /// + /// Contains extension methods for registering into a instance. + /// + public static class OpenTelemetryLoggingExtensions + { + /// + /// Adds an OpenTelemetry named 'OpenTelemetry' to the . + /// + /// + /// Notes: + /// + /// + /// This is safe to be called multiple times. Only a single will be created for a given and only a single registered with the . + /// + /// + /// This method should be called by application host code. Library + /// authors should call + /// instead. + /// + /// + /// + /// The to use. + /// . + public static OpenTelemetryLoggingBuilder AddOpenTelemetry(this ILoggingBuilder builder) + { + Guard.ThrowIfNull(builder); + + builder.AddConfiguration(); + + // Note: This will bind logger options element (eg "Logging:OpenTelemetry") to OpenTelemetryLoggerOptions + LoggerProviderOptions.RegisterProviderOptions(builder.Services); + + builder.Services.ConfigureOpenTelemetryLogging( + loggerBuilder => + { + loggerBuilder.ConfigureBuilder((sp, loggerBuilder) => + { + var options = sp.GetRequiredService>().Value; + + if (options.ResourceBuilder != null) + { + loggerBuilder.SetResourceBuilder(options.ResourceBuilder); + + options.ResourceBuilder = null; + } + + foreach (var processor in options.Processors) + { + loggerBuilder.AddProcessor(processor); + } + + options.Processors.Clear(); + }); + }); + + builder.Services.TryAddEnumerable( + ServiceDescriptor.Singleton( + sp => new OpenTelemetryLoggerProvider( + sp.GetRequiredService>().Value, + sp.GetRequiredService(), + disposeProvider: false))); + + return new OpenTelemetryLoggingBuilder(builder.Services); + } + + /// + /// Adds an OpenTelemetry named 'OpenTelemetry' to the . + /// + /// + /// The to use. + /// Callback action to configure the . + /// . + public static OpenTelemetryLoggingBuilder AddOpenTelemetry( + this ILoggingBuilder builder, + Action configureOptions) + { + Guard.ThrowIfNull(configureOptions); + + var loggingBuilder = AddOpenTelemetry(builder); + + loggingBuilder.Services.Configure(configureOptions); + + return loggingBuilder; + } + + /// + /// Adds an OpenTelemetry named 'OpenTelemetry' to the + /// . + /// + /// + /// Notes: + /// + /// + /// The supplied will NOT be disposed when + /// the built from is disposed. + /// + /// + /// Only a single OpenTelemetry can be registered for a + /// given . Additional calls to this + /// method will be ignored. + /// + /// + /// This method should be called by application host code. Library + /// authors should call + /// instead. + /// + /// + /// + /// The to + /// use. + /// . + /// The supplied for call + /// chaining. + public static ILoggingBuilder AddOpenTelemetry( + this ILoggingBuilder builder, + LoggerProvider loggerProvider) + => AddOpenTelemetry(builder, loggerProvider, configureOptions: null, disposeProvider: false); + + /// + /// Adds an OpenTelemetry named 'OpenTelemetry' to the + /// . + /// + /// + /// The to + /// use. + /// . + /// Optional callback action to configure . + /// The supplied for call + /// chaining. + public static ILoggingBuilder AddOpenTelemetry( + this ILoggingBuilder builder, + LoggerProvider loggerProvider, + Action configureOptions) + => AddOpenTelemetry(builder, loggerProvider, configureOptions, disposeProvider: false); + + /// + /// Adds an OpenTelemetry named 'OpenTelemetry' to the + /// . + /// + /// + /// Notes: + /// + /// + /// Only a single OpenTelemetry can be registered for a + /// given . Additional calls to this + /// method will be ignored. + /// + /// + /// This method should be called by application host code. Library + /// authors should call + /// instead. + /// + /// + /// + /// The to + /// use. + /// . + /// Optional callback action to configure . + /// Controls whether or not the supplied + /// will be disposed when the is disposed. + /// The supplied for call + /// chaining. + public static ILoggingBuilder AddOpenTelemetry( + this ILoggingBuilder builder, + LoggerProvider loggerProvider, + Action? configureOptions, + bool disposeProvider) + { + Guard.ThrowIfNull(builder); + Guard.ThrowIfNull(loggerProvider); + + // Note: Currently if multiple OpenTelemetryLoggerProvider instances + // are added to the same ILoggingBuilder everything after the first + // is silently ignored. + + if (configureOptions != null) + { + builder.Services.Configure(configureOptions); + } + + builder.Services.TryAddEnumerable( + ServiceDescriptor.Singleton(sp => + { + var options = sp.GetRequiredService>().Value; + + if (options.Processors.Count > 0 || options.ResourceBuilder != null) + { + throw new NotSupportedException("Configuring processors or resource via options for an external provider is not supported."); + } + + return new OpenTelemetryLoggerProvider( + options, + loggerProvider, + disposeProvider); + })); + + return builder; + } + } +} diff --git a/src/OpenTelemetry/Logs/LogRecord.cs b/src/OpenTelemetry/Logs/LogRecord.cs index 61c8199391c..f417ee86693 100644 --- a/src/OpenTelemetry/Logs/LogRecord.cs +++ b/src/OpenTelemetry/Logs/LogRecord.cs @@ -32,6 +32,7 @@ namespace OpenTelemetry.Logs public sealed class LogRecord { internal LogRecordData Data; + internal LogRecordILoggerData ILoggerData; internal List>? AttributeStorage; internal List? BufferedScopes; internal int PoolReferenceCount = int.MaxValue; @@ -58,20 +59,39 @@ internal LogRecord( Exception? exception, IReadOnlyList>? stateValues) { - this.Data = new(Activity.Current) + var activity = Activity.Current; + + this.Data = new(activity) { TimestampBacking = timestamp, + Severity = (LogRecordSeverity)logLevel, + }; + this.ILoggerData = new() + { + TraceState = activity?.TraceStateString, CategoryName = categoryName, - LogLevel = logLevel, + FormattedMessage = formattedMessage, EventId = eventId, - Message = formattedMessage, Exception = exception, + State = state, }; + if (stateValues != null && stateValues.Count > 0) + { + var lastAttribute = stateValues[stateValues.Count - 1]; + this.Data.Body = lastAttribute.Key == "{OriginalFormat}" + ? lastAttribute.Value as string + : null; + } + + this.Data.Body ??= formattedMessage; + + this.InstrumentationScope = null; + + this.Attributes = stateValues; + this.ScopeProvider = scopeProvider; - this.StateValues = stateValues; - this.State = state; } /// @@ -116,48 +136,72 @@ public ActivityTraceFlags TraceFlags } /// - /// Gets or sets the log trace state. + /// Gets or sets the log trace state. Only set if is enabled. /// + /// + /// Note: is only set when emitting logs through . + /// public string? TraceState { - get => this.Data.TraceState; - set => this.Data.TraceState = value; + get => this.ILoggerData.TraceState; + set => this.ILoggerData.TraceState = value; } /// /// Gets or sets the log category name. /// + /// + /// Note: is only set when emitting logs through . + /// public string? CategoryName { - get => this.Data.CategoryName; - set => this.Data.CategoryName = value; + get => this.ILoggerData.CategoryName; + set => this.ILoggerData.CategoryName = value; } /// /// Gets or sets the log . /// + [Obsolete("Use Severity instead LogLevel will be removed in a future version.")] public LogLevel LogLevel { - get => this.Data.LogLevel; - set => this.Data.LogLevel = value; + get => (LogLevel)(this.Data.Severity ?? LogRecordSeverity.Trace); + set => this.Data.Severity = (LogRecordSeverity)value; } /// /// Gets or sets the log . /// + /// + /// Note: is only set when emitting logs through . + /// public EventId EventId { - get => this.Data.EventId; - set => this.Data.EventId = value; + get => this.ILoggerData.EventId; + set => this.ILoggerData.EventId = value; } /// - /// Gets or sets the log formatted message. + /// Gets or sets the log formatted message. Only set if is enabled. /// + /// + /// Note: is only set when emitting logs through . + /// public string? FormattedMessage { - get => this.Data.Message; - set => this.Data.Message = value; + get => this.ILoggerData.FormattedMessage; + set => this.ILoggerData.FormattedMessage = value; + } + + /// + /// Gets or sets the log body. + /// + public string? Body + { + get => this.Data.Body; + set => this.Data.Body = value; } /// @@ -165,24 +209,59 @@ public string? FormattedMessage /// langword="null"/> when is enabled. /// - public object? State { get; set; } + /// + /// Note: is only set when emitting logs through . + /// + [Obsolete("State cannot be accessed safely outside of an ILogger.Log call stack. It will be removed in a future version.")] + public object? State + { + get => this.ILoggerData.State; + set => this.ILoggerData.State = value; + } /// /// Gets or sets the parsed state values attached to the log. Set when is enabled /// otherwise . /// - public IReadOnlyList>? StateValues { get; set; } + [Obsolete("Use Attributes instead StateValues will be removed in a future version.")] + public IReadOnlyList>? StateValues + { + get => this.Attributes; + set => this.Attributes = value; + } + + /// + /// Gets or sets the attributes attached to the log. + /// + public IReadOnlyList>? Attributes { get; set; } /// /// Gets or sets the log . /// + /// + /// Note: is only set when emitting logs through . + /// public Exception? Exception { - get => this.Data.Exception; - set => this.Data.Exception = value; + get => this.ILoggerData.Exception; + set => this.ILoggerData.Exception = value; } + /// + /// Gets or sets the log . + /// + public LogRecordSeverity? Severity + { + get => this.Data.Severity; + set => this.Data.Severity = value; + } + + /// + /// Gets the log . + /// + public InstrumentationScope? InstrumentationScope { get; internal set; } + internal IExternalScopeProvider? ScopeProvider { get; set; } /// @@ -191,6 +270,9 @@ public Exception? Exception /// this method. /// /// State. + /// + /// Note: Scopes are only supported when emitting logs through . + /// /// The callback to be executed for every scope object. /// The state object to be passed into the callback. public void ForEachScope(Action callback, TState state) @@ -206,21 +288,12 @@ public void ForEachScope(Action callback, TState ScopeForEachState.ForEachScope(scope, forEachScopeState); } } - else if (this.ScopeProvider != null) + else { - this.ScopeProvider.ForEachScope(ScopeForEachState.ForEachScope, forEachScopeState); + this.ScopeProvider?.ForEachScope(ScopeForEachState.ForEachScope, forEachScopeState); } } - /// - /// Gets a reference to the for the log message. - /// - /// . - internal ref LogRecordData GetDataRef() - { - return ref this.Data; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ResetReferenceCount() { @@ -243,19 +316,12 @@ internal int RemoveReference() // can be safely processed outside of the log call chain. internal void Buffer() { - // Note: State values are buffered because some states are not safe + // Note: Attributes are buffered because some states are not safe // to access outside of the log call chain. See: // https://github.com/open-telemetry/opentelemetry-dotnet/issues/2905 - this.BufferLogStateValues(); + this.BufferLogAttributes(); this.BufferLogScopes(); - - // Note: There is no buffering of "State" only "StateValues". We - // don't inspect "object State" at all. It is undefined what - // exporters will do with "State". Some might ignore it, some might - // attempt to access it as a list. That is potentially dangerous. - // TODO: Investigate what to do here. Should we obsolete State and - // just use the StateValues design? } internal LogRecord Copy() @@ -267,8 +333,8 @@ internal LogRecord Copy() return new() { Data = this.Data, - State = this.State, - StateValues = this.StateValues == null ? null : new List>(this.StateValues), + ILoggerData = this.ILoggerData, + Attributes = this.Attributes == null ? null : new List>(this.Attributes), BufferedScopes = this.BufferedScopes == null ? null : new List(this.BufferedScopes), }; } @@ -278,24 +344,24 @@ internal LogRecord Copy() /// they can be safely processed after the log message lifecycle has /// ended. /// - private void BufferLogStateValues() + private void BufferLogAttributes() { - var stateValues = this.StateValues; - if (stateValues == null || stateValues == this.AttributeStorage) + var attributes = this.Attributes; + if (attributes == null || attributes == this.AttributeStorage) { return; } - var attributeStorage = this.AttributeStorage ??= new List>(stateValues.Count); + var attributeStorage = this.AttributeStorage ??= new List>(attributes.Count); // Note: AddRange here will copy all of the KeyValuePairs from // stateValues to AttributeStorage. This "captures" the state and // fixes issues where the values are generated at enumeration time // like // https://github.com/open-telemetry/opentelemetry-dotnet/issues/2905. - attributeStorage.AddRange(stateValues); + attributeStorage.AddRange(attributes); - this.StateValues = attributeStorage; + this.Attributes = attributeStorage; } /// @@ -316,6 +382,16 @@ private void BufferLogScopes() this.ScopeProvider = null; } + internal struct LogRecordILoggerData + { + public string? TraceState; + public string? CategoryName; + public EventId EventId; + public string? FormattedMessage; + public Exception? Exception; + public object? State; + } + private readonly struct ScopeForEachState { public static readonly Action> ForEachScope = (object? scope, ScopeForEachState state) => diff --git a/src/OpenTelemetry/Logs/LogRecordAttributeList.cs b/src/OpenTelemetry/Logs/LogRecordAttributeList.cs deleted file mode 100644 index 385ba8f108e..00000000000 --- a/src/OpenTelemetry/Logs/LogRecordAttributeList.cs +++ /dev/null @@ -1,326 +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. -// - -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Logs -{ - /// - /// Stores attributes to be added to a log message. - /// - internal struct LogRecordAttributeList : IReadOnlyList> - { - internal const int OverflowAdditionalCapacity = 8; - internal List>? OverflowAttributes; - private KeyValuePair attribute1; - private KeyValuePair attribute2; - private KeyValuePair attribute3; - private KeyValuePair attribute4; - private KeyValuePair attribute5; - private KeyValuePair attribute6; - private KeyValuePair attribute7; - private KeyValuePair attribute8; - private int count; - - /// - public readonly int Count => this.count; - - /// - public KeyValuePair this[int index] - { - readonly get - { - if (this.OverflowAttributes is not null) - { - Debug.Assert(index < this.OverflowAttributes.Count, "Invalid index accessed."); - return this.OverflowAttributes[index]; - } - - if ((uint)index >= (uint)this.count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - return index switch - { - 0 => this.attribute1, - 1 => this.attribute2, - 2 => this.attribute3, - 3 => this.attribute4, - 4 => this.attribute5, - 5 => this.attribute6, - 6 => this.attribute7, - 7 => this.attribute8, - _ => default, // we shouldn't come here anyway. - }; - } - - set - { - if (this.OverflowAttributes is not null) - { - Debug.Assert(index < this.OverflowAttributes.Count, "Invalid index accessed."); - this.OverflowAttributes[index] = value; - return; - } - - if ((uint)index >= (uint)this.count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - switch (index) - { - case 0: this.attribute1 = value; break; - case 1: this.attribute2 = value; break; - case 2: this.attribute3 = value; break; - case 3: this.attribute4 = value; break; - case 4: this.attribute5 = value; break; - case 5: this.attribute6 = value; break; - case 6: this.attribute7 = value; break; - case 7: this.attribute8 = value; break; - default: - Debug.Assert(false, "Unreachable code executed."); - break; - } - } - } - - /// - /// Add an attribute. - /// - /// Attribute name. - /// Attribute value. - [EditorBrowsable(EditorBrowsableState.Never)] - public object? this[string key] - { - // Note: This only exists to enable collection initializer syntax - // like { ["key"] = value }. - set => this.Add(new KeyValuePair(key, value)); - } - - /// - /// Create a collection from an enumerable. - /// - /// Source attributes. - /// . - public static LogRecordAttributeList CreateFromEnumerable(IEnumerable> attributes) - { - Guard.ThrowIfNull(attributes); - - LogRecordAttributeList logRecordAttributes = default; - logRecordAttributes.OverflowAttributes = new(attributes); - logRecordAttributes.count = logRecordAttributes.OverflowAttributes.Count; - return logRecordAttributes; - } - - /// - /// Add an attribute. - /// - /// Attribute name. - /// Attribute value. - public void Add(string key, object? value) - => this.Add(new KeyValuePair(key, value)); - - /// - /// Add an attribute. - /// - /// Attribute. - public void Add(KeyValuePair attribute) - { - if (this.OverflowAttributes is not null) - { - this.OverflowAttributes.Add(attribute); - this.count++; - return; - } - - Debug.Assert(this.count <= 8, "Item added beyond struct capacity."); - - switch (this.count) - { - case 0: this.attribute1 = attribute; break; - case 1: this.attribute2 = attribute; break; - case 2: this.attribute3 = attribute; break; - case 3: this.attribute4 = attribute; break; - case 4: this.attribute5 = attribute; break; - case 5: this.attribute6 = attribute; break; - case 6: this.attribute7 = attribute; break; - case 7: this.attribute8 = attribute; break; - case 8: - Debug.Assert(this.OverflowAttributes is null, "Overflow attributes already created."); - this.MoveAttributesToTheOverflowList(); - Debug.Assert(this.OverflowAttributes is not null, "Overflow attributes creation failure."); - this.OverflowAttributes!.Add(attribute); - break; - default: - // We shouldn't come here. - Debug.Assert(this.OverflowAttributes is null, "Unreachable code executed."); - return; - } - - this.count++; - } - - /// - /// Returns an enumerator that iterates through the . - /// - /// . - public readonly Enumerator GetEnumerator() - => new(in this); - - /// - readonly IEnumerator> IEnumerable>.GetEnumerator() => this.GetEnumerator(); - - /// - readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - - internal readonly void ApplyToLogRecord(LogRecord logRecord) - { - int count = this.count; - if (count <= 0) - { - logRecord.StateValues = null; - return; - } - - var overflowAttributes = this.OverflowAttributes; - if (overflowAttributes != null) - { - // An allocation has already occurred, just use the buffer. - logRecord.StateValues = overflowAttributes; - return; - } - - Debug.Assert(count <= 8, "Invalid size detected."); - - var attributeStorage = logRecord.AttributeStorage ??= new List>(OverflowAdditionalCapacity); - - try - { - // TODO: Perf test this, adjust as needed. - - attributeStorage.Add(this.attribute1); - if (count == 1) - { - return; - } - - attributeStorage.Add(this.attribute2); - if (count == 2) - { - return; - } - - attributeStorage.Add(this.attribute3); - if (count == 3) - { - return; - } - - attributeStorage.Add(this.attribute4); - if (count == 4) - { - return; - } - - attributeStorage.Add(this.attribute5); - if (count == 5) - { - return; - } - - attributeStorage.Add(this.attribute6); - if (count == 6) - { - return; - } - - attributeStorage.Add(this.attribute7); - if (count == 7) - { - return; - } - - attributeStorage.Add(this.attribute8); - } - finally - { - logRecord.StateValues = attributeStorage; - } - } - - private void MoveAttributesToTheOverflowList() - { - this.OverflowAttributes = new(16) - { - { this.attribute1 }, - { this.attribute2 }, - { this.attribute3 }, - { this.attribute4 }, - { this.attribute5 }, - { this.attribute6 }, - { this.attribute7 }, - { this.attribute8 }, - }; - } - - /// - /// Enumerates the elements of a . - /// - public struct Enumerator : IEnumerator>, IEnumerator - { - private LogRecordAttributeList attributes; - private int index; - - internal Enumerator(in LogRecordAttributeList attributes) - { - this.index = -1; - this.attributes = attributes; - } - - /// - public readonly KeyValuePair Current - => this.attributes[this.index]; - - /// - readonly object IEnumerator.Current => this.Current; - - /// - public bool MoveNext() - { - this.index++; - return this.index < this.attributes.Count; - } - - /// - public readonly void Dispose() - { - } - - /// - readonly void IEnumerator.Reset() - => throw new NotSupportedException(); - } - } -} diff --git a/src/OpenTelemetry/Logs/LogRecordData.cs b/src/OpenTelemetry/Logs/LogRecordData.cs deleted file mode 100644 index 538bf0a3666..00000000000 --- a/src/OpenTelemetry/Logs/LogRecordData.cs +++ /dev/null @@ -1,143 +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. -// - -#nullable enable - -using System; -using System.Diagnostics; -using Microsoft.Extensions.Logging; - -namespace OpenTelemetry.Logs -{ - /// - /// Stores details about a log message. - /// - internal struct LogRecordData - { - internal DateTime TimestampBacking = DateTime.UtcNow; - - /// - /// Initializes a new instance of the struct. - /// - public LogRecordData() - : this(activity: null) - { - } - - /// - /// Initializes a new instance of the struct. - /// - /// - /// Note: The property is initialized to automatically. - /// - /// Optional used to populate context fields. - public LogRecordData(Activity? activity) - { - if (activity != null) - { - this.TraceId = activity.TraceId; - this.SpanId = activity.SpanId; - this.TraceState = activity.TraceStateString; - this.TraceFlags = activity.ActivityTraceFlags; - } - else - { - this.TraceId = default; - this.SpanId = default; - this.TraceState = null; - this.TraceFlags = ActivityTraceFlags.None; - } - } - - /// - /// Gets or sets the log timestamp. - /// - /// - /// Note: If is set to a value with it will be automatically converted to - /// UTC using . - /// - public DateTime Timestamp - { - readonly get => this.TimestampBacking; - set { this.TimestampBacking = value.Kind == DateTimeKind.Local ? value.ToUniversalTime() : value; } - } - - /// - /// Gets or sets the log . - /// - public ActivityTraceId TraceId { get; set; } - - /// - /// Gets or sets the log . - /// - public ActivitySpanId SpanId { get; set; } - - /// - /// Gets or sets the log . - /// - public ActivityTraceFlags TraceFlags { get; set; } - - /// - /// Gets or sets the log trace state. - /// - public string? TraceState { get; set; } - - /// - /// Gets or sets the log category name. - /// - public string? CategoryName { get; set; } = null; - - /// - /// Gets or sets the log . - /// - public LogLevel LogLevel { get; set; } = LogLevel.Trace; - - /// - /// Gets or sets the log . - /// - public EventId EventId { get; set; } = default; - - /// - /// Gets or sets the log message. - /// - public string? Message { get; set; } = null; - - /// - /// Gets or sets the log . - /// - public Exception? Exception { get; set; } = null; - - internal static void SetActivityContext(ref LogRecordData data, Activity? activity = null) - { - if (activity != null) - { - data.TraceId = activity.TraceId; - data.SpanId = activity.SpanId; - data.TraceState = activity.TraceStateString; - data.TraceFlags = activity.ActivityTraceFlags; - } - else - { - data.TraceId = default; - data.SpanId = default; - data.TraceState = null; - data.TraceFlags = ActivityTraceFlags.None; - } - } - } -} diff --git a/src/OpenTelemetry/Logs/LoggerProviderExtensions.cs b/src/OpenTelemetry/Logs/LoggerProviderExtensions.cs new file mode 100644 index 00000000000..f0c1d123bf6 --- /dev/null +++ b/src/OpenTelemetry/Logs/LoggerProviderExtensions.cs @@ -0,0 +1,117 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Threading; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + /// + /// Contains extension methods for the class. + /// + public static class LoggerProviderExtensions + { + /// + /// Add a processor to the . + /// + /// + /// Note: The supplied will be + /// automatically disposed when then the is disposed. + /// + /// instance on which ForceFlush will be called. + /// Log processor to add. + /// The supplied for chaining. + public static LoggerProvider AddProcessor(this LoggerProvider provider, BaseProcessor processor) + { + Guard.ThrowIfNull(provider); + Guard.ThrowIfNull(processor); + + if (provider is LoggerProviderSdk loggerProviderSdk) + { + loggerProviderSdk.AddProcessor(processor); + } + + return provider; + } + + /// + /// Flushes all the processors registered under , blocks the current thread + /// until flush completed, shutdown signaled or timed out. + /// + /// instance on which ForceFlush will be called. + /// + /// The number (non-negative) of milliseconds to wait, or + /// Timeout.Infinite to wait indefinitely. + /// + /// + /// Returns true when force flush succeeded; otherwise, false. + /// + /// + /// Thrown when the timeoutMilliseconds is smaller than -1. + /// + /// + /// This function guarantees thread-safety. + /// + public static bool ForceFlush(this LoggerProvider provider, int timeoutMilliseconds = Timeout.Infinite) + { + Guard.ThrowIfNull(provider); + Guard.ThrowIfInvalidTimeout(timeoutMilliseconds); + + if (provider is LoggerProviderSdk loggerProviderSdk) + { + return loggerProviderSdk.ForceFlush(timeoutMilliseconds); + } + + return true; + } + + /// + /// Attempts to shutdown the , blocks the current thread until + /// shutdown completed or timed out. + /// + /// instance on which Shutdown will be called. + /// + /// The number (non-negative) of milliseconds to wait, or + /// Timeout.Infinite to wait indefinitely. + /// + /// + /// Returns true when shutdown succeeded; otherwise, false. + /// + /// + /// Thrown when the timeoutMilliseconds is smaller than -1. + /// + /// + /// This function guarantees thread-safety. Only the first call will + /// win, subsequent calls will be no-op. + /// + public static bool Shutdown(this LoggerProvider provider, int timeoutMilliseconds = Timeout.Infinite) + { + Guard.ThrowIfNull(provider); + Guard.ThrowIfInvalidTimeout(timeoutMilliseconds); + + if (provider is LoggerProviderSdk loggerProviderSdk) + { + return loggerProviderSdk.Shutdown(timeoutMilliseconds); + } + + return true; + } + } +} diff --git a/src/OpenTelemetry/Logs/LoggerProviderSdk.cs b/src/OpenTelemetry/Logs/LoggerProviderSdk.cs new file mode 100644 index 00000000000..175e118b676 --- /dev/null +++ b/src/OpenTelemetry/Logs/LoggerProviderSdk.cs @@ -0,0 +1,229 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading; +using Microsoft.Extensions.DependencyInjection; +using OpenTelemetry.Internal; +using OpenTelemetry.Resources; + +using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper< + OpenTelemetry.Logs.LoggerProviderBuilderSdk, + OpenTelemetry.Logs.LoggerProviderSdk, + OpenTelemetry.Logs.LoggerProviderBuilderState>; + +namespace OpenTelemetry.Logs; + +/// +/// SDK implementation. +/// +internal sealed class LoggerProviderSdk : LoggerProvider +{ + private readonly ServiceProvider? ownedServiceProvider; + private readonly List instrumentations = new(); + private ILogRecordPool? threadStaticPool = LogRecordThreadStaticPool.Instance; + private int shutdownCount; + private bool disposed; + + public LoggerProviderSdk( + IServiceProvider serviceProvider, + bool ownsServiceProvider) + { + OpenTelemetrySdkEventSource.Log.LoggerProviderSdkEvent("Building LoggerProviderSdk."); + + if (ownsServiceProvider) + { + this.ownedServiceProvider = serviceProvider as ServiceProvider; + + Debug.Assert(this.ownedServiceProvider != null, "ownedServiceProvider was null"); + } + + var state = new LoggerProviderBuilderState(serviceProvider, this); + + CallbackHelper.InvokeRegisteredConfigureStateCallbacks( + serviceProvider, + state); + + foreach (var processor in state.Processors) + { + this.AddProcessor(processor); + } + + foreach (var instrumentation in state.Instrumentation) + { + this.instrumentations.Add(instrumentation.Instance); + } + + this.Resource = (state.ResourceBuilder ?? ResourceBuilder.CreateDefault()).Build(); + + OpenTelemetrySdkEventSource.Log.LoggerProviderSdkEvent("LoggerProviderSdk built successfully."); + } + + public Resource Resource { get; } + + public List Instrumentations => this.instrumentations; + + public BaseProcessor? Processor { get; private set; } + + public ILogRecordPool LogRecordPool => this.threadStaticPool ?? LogRecordSharedPool.Current; + + public void AddProcessor(BaseProcessor processor) + { + OpenTelemetrySdkEventSource.Log.LoggerProviderSdkEvent("Started adding processor."); + + Guard.ThrowIfNull(processor); + + processor.SetParentProvider(this); + + StringBuilder processorAdded = new StringBuilder(); + + if (this.threadStaticPool != null && this.ContainsBatchProcessor(processor)) + { + OpenTelemetrySdkEventSource.Log.LoggerProviderSdkEvent("Using shared thread pool."); + + this.threadStaticPool = null; + } + + if (this.Processor == null) + { + processorAdded.Append("Setting processor to "); + processorAdded.Append(processor); + + this.Processor = processor; + } + else if (this.Processor is CompositeProcessor compositeProcessor) + { + processorAdded.Append("Adding processor "); + processorAdded.Append(processor); + processorAdded.Append(" to composite processor"); + + compositeProcessor.AddProcessor(processor); + } + else + { + processorAdded.Append("Creating new composite processor with processor "); + processorAdded.Append(this.Processor); + processorAdded.Append(" and adding new processor "); + processorAdded.Append(processor); + + var newCompositeProcessor = new CompositeProcessor(new[] + { + this.Processor, + }); + newCompositeProcessor.SetParentProvider(this); + newCompositeProcessor.AddProcessor(processor); + this.Processor = newCompositeProcessor; + } + + OpenTelemetrySdkEventSource.Log.LoggerProviderSdkEvent($"Completed adding processor = \"{processorAdded}\"."); + } + + public bool ForceFlush(int timeoutMilliseconds = Timeout.Infinite) + { + try + { + return this.Processor?.ForceFlush(timeoutMilliseconds) ?? true; + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.LoggerProviderException(nameof(LoggerProviderSdk.ForceFlush), ex); + return false; + } + } + + public bool Shutdown(int timeoutMilliseconds) + { + if (Interlocked.Increment(ref this.shutdownCount) > 1) + { + return false; // shutdown already called + } + + try + { + return this.Processor?.Shutdown(timeoutMilliseconds) ?? true; + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.LoggerProviderException(nameof(LoggerProviderSdk.Shutdown), ex); + return false; + } + } + + public bool ContainsBatchProcessor(BaseProcessor processor) + { + if (processor is BatchExportProcessor) + { + return true; + } + else if (processor is CompositeProcessor compositeProcessor) + { + var current = compositeProcessor.Head; + while (current != null) + { + if (this.ContainsBatchProcessor(current.Value)) + { + return true; + } + + current = current.Next; + } + } + + return false; + } + + /// + public override Logger GetLogger(LoggerOptions options) + { + return new LoggerSdk(this, options); + } + + /// + protected override void Dispose(bool disposing) + { + if (!this.disposed) + { + if (disposing) + { + if (this.instrumentations != null) + { + foreach (var item in this.instrumentations) + { + (item as IDisposable)?.Dispose(); + } + + this.instrumentations.Clear(); + } + + // Wait for up to 5 seconds grace period + this.Processor?.Shutdown(5000); + this.Processor?.Dispose(); + + this.ownedServiceProvider?.Dispose(); + } + + this.disposed = true; + OpenTelemetrySdkEventSource.Log.ProviderDisposed(nameof(LoggerProviderSdk)); + } + + base.Dispose(disposing); + } +} diff --git a/src/OpenTelemetry/Logs/LoggerSdk.cs b/src/OpenTelemetry/Logs/LoggerSdk.cs new file mode 100644 index 00000000000..2867b72f5e0 --- /dev/null +++ b/src/OpenTelemetry/Logs/LoggerSdk.cs @@ -0,0 +1,125 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs; + +/// +/// SDK implementation. +/// +internal sealed class LoggerSdk : Logger +{ + private readonly LoggerProviderSdk loggerProvider; + private string? eventDomain; + + public LoggerSdk( + LoggerProviderSdk loggerProvider, + LoggerOptions options) + : base(options) + { + Guard.ThrowIfNull(loggerProvider); + + this.loggerProvider = loggerProvider; + } + + /// + public override void EmitEvent(string name, in LogRecordData data, in LogRecordAttributeList attributes = default) + { + Guard.ThrowIfNullOrWhitespace(name); + + string eventDomain = this.EnsureEventDomain(); + + var provider = this.loggerProvider; + var processor = provider.Processor; + if (processor != null) + { + var pool = provider.LogRecordPool; + + var logRecord = pool.Rent(); + + logRecord.Data = data; + logRecord.ILoggerData = default; + + logRecord.InstrumentationScope = this.Options.InstrumentationScope; + + var exportedAttributes = attributes.Export(ref logRecord.AttributeStorage, additionalCapacity: 2); + + Debug.Assert(exportedAttributes != null, "exportedAttributes was null"); + + exportedAttributes!.Add(new KeyValuePair("event.name", name)); + exportedAttributes!.Add(new KeyValuePair("event.domain", eventDomain)); + + logRecord.Attributes = exportedAttributes; + + processor.OnEnd(logRecord); + + // Attempt to return the LogRecord to the pool. This will no-op + // if a batch exporter has added a reference. + pool.Return(logRecord); + } + } + + /// + public override void EmitLog(in LogRecordData data, in LogRecordAttributeList attributes = default) + { + var provider = this.loggerProvider; + var processor = provider.Processor; + if (processor != null) + { + var pool = provider.LogRecordPool; + + var logRecord = pool.Rent(); + + logRecord.Data = data; + logRecord.ILoggerData = default; + + logRecord.InstrumentationScope = this.Options.InstrumentationScope; + + logRecord.Attributes = attributes.Export(ref logRecord.AttributeStorage); + + processor.OnEnd(logRecord); + + // Attempt to return the LogRecord to the pool. This will no-op + // if a batch exporter has added a reference. + pool.Return(logRecord); + } + } + + private string EnsureEventDomain() + { + string? eventDomain = this.eventDomain; + + if (eventDomain == null) + { + eventDomain = this.Options.EventDomain; + + if (string.IsNullOrWhiteSpace(eventDomain)) + { + throw new InvalidOperationException($"Events cannot be emitted through the Logger '{this.Options.InstrumentationScope.Name}' because it does not have a configured EventDomain."); + } + + this.eventDomain = eventDomain; + } + + return eventDomain!; + } +} diff --git a/src/OpenTelemetry/Logs/NoopLoggerProvider.cs b/src/OpenTelemetry/Logs/NoopLoggerProvider.cs new file mode 100644 index 00000000000..0c40c23d25e --- /dev/null +++ b/src/OpenTelemetry/Logs/NoopLoggerProvider.cs @@ -0,0 +1,23 @@ +// +// 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. +// + +#nullable enable + +namespace OpenTelemetry.Logs; + +internal sealed class NoopLoggerProvider : LoggerProvider +{ +} diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs b/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs deleted file mode 100644 index 91698d1123a..00000000000 --- a/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs +++ /dev/null @@ -1,136 +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. -// - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Microsoft.Extensions.Logging; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Logs -{ - internal sealed class OpenTelemetryLogger : ILogger - { - private readonly string categoryName; - private readonly OpenTelemetryLoggerProvider provider; - - internal OpenTelemetryLogger(string categoryName, OpenTelemetryLoggerProvider provider) - { - Guard.ThrowIfNull(categoryName); - Guard.ThrowIfNull(provider); - - this.categoryName = categoryName; - this.provider = provider; - } - - internal IExternalScopeProvider? ScopeProvider { get; set; } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) - { - if (!this.IsEnabled(logLevel) - || Sdk.SuppressInstrumentation) - { - return; - } - - var provider = this.provider; - var processor = provider.Processor; - if (processor != null) - { - var pool = provider.LogRecordPool; - - var record = pool.Rent(); - - record.ScopeProvider = provider.IncludeScopes ? this.ScopeProvider : null; - record.State = provider.ParseStateValues ? null : state; - record.StateValues = provider.ParseStateValues ? ParseState(record, state) : null; - - ref LogRecordData data = ref record.Data; - - data.TimestampBacking = DateTime.UtcNow; - data.CategoryName = this.categoryName; - data.LogLevel = logLevel; - data.EventId = eventId; - data.Message = provider.IncludeFormattedMessage ? formatter?.Invoke(state, exception) : null; - data.Exception = exception; - - LogRecordData.SetActivityContext(ref data, Activity.Current); - - processor.OnEnd(record); - - record.ScopeProvider = null; - - // Attempt to return the LogRecord to the pool. This will no-op - // if a batch exporter has added a reference. - pool.Return(record); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool IsEnabled(LogLevel logLevel) - { - return logLevel != LogLevel.None; - } - - public IDisposable BeginScope(TState state) => this.ScopeProvider?.Push(state) ?? NullScope.Instance; - - private static IReadOnlyList> ParseState(LogRecord logRecord, TState state) - { - /* TODO: Enable this if/when LogRecordAttributeList becomes public. - if (state is LogRecordAttributeList logRecordAttributes) - { - logRecordAttributes.ApplyToLogRecord(logRecord); - return logRecord.AttributeStorage!; - } - else*/ - if (state is IReadOnlyList> stateList) - { - return stateList; - } - else if (state is IEnumerable> stateValues) - { - var attributeStorage = logRecord.AttributeStorage; - if (attributeStorage == null) - { - return logRecord.AttributeStorage = new List>(stateValues); - } - else - { - attributeStorage.AddRange(stateValues); - return attributeStorage; - } - } - else - { - var attributeStorage = logRecord.AttributeStorage ??= new List>(LogRecordPoolHelper.DefaultMaxNumberOfAttributes); - attributeStorage.Add(new KeyValuePair(string.Empty, state)); - return attributeStorage; - } - } - - private sealed class NullScope : IDisposable - { - public static NullScope Instance { get; } = new(); - - public void Dispose() - { - } - } - } -} diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs b/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs deleted file mode 100644 index 2d52d20399f..00000000000 --- a/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs +++ /dev/null @@ -1,271 +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. -// - -#nullable enable - -using System; -using System.Collections; -using System.Text; -using System.Threading; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using OpenTelemetry.Internal; -using OpenTelemetry.Resources; - -namespace OpenTelemetry.Logs -{ - /// - /// An implementation for exporting logs using OpenTelemetry. - /// - [ProviderAlias("OpenTelemetry")] - public class OpenTelemetryLoggerProvider : BaseProvider, ILoggerProvider, ISupportExternalScope - { - internal readonly bool IncludeScopes; - internal readonly bool IncludeFormattedMessage; - internal readonly bool ParseStateValues; - internal BaseProcessor? Processor; - internal Resource Resource; - private readonly Hashtable loggers = new(); - private ILogRecordPool? threadStaticPool = LogRecordThreadStaticPool.Instance; - private bool disposed; - - static OpenTelemetryLoggerProvider() - { - // Accessing Sdk class is just to trigger its static ctor, - // which sets default Propagators and default Activity Id format - _ = Sdk.SuppressInstrumentation; - } - - /// - /// Initializes a new instance of the class. - /// - /// . - public OpenTelemetryLoggerProvider(IOptionsMonitor options) - : this(options?.CurrentValue ?? throw new ArgumentNullException(nameof(options))) - { - } - - internal OpenTelemetryLoggerProvider() - : this(new OpenTelemetryLoggerOptions()) - { - } - - internal OpenTelemetryLoggerProvider(Action configure) - : this(BuildOptions(configure)) - { - } - - internal OpenTelemetryLoggerProvider(OpenTelemetryLoggerOptions options) - { - OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Building OpenTelemetryLoggerProvider."); - - Guard.ThrowIfNull(options); - - this.IncludeScopes = options.IncludeScopes; - this.IncludeFormattedMessage = options.IncludeFormattedMessage; - this.ParseStateValues = options.ParseStateValues; - - this.Resource = options.ResourceBuilder.Build(); - - foreach (var processor in options.Processors) - { - this.AddProcessor(processor); - } - - OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("OpenTelemetryLoggerProvider built successfully."); - } - - internal IExternalScopeProvider? ScopeProvider { get; private set; } - - internal ILogRecordPool LogRecordPool => this.threadStaticPool ?? LogRecordSharedPool.Current; - - /// - void ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider) - { - this.ScopeProvider = scopeProvider; - - lock (this.loggers) - { - foreach (DictionaryEntry entry in this.loggers) - { - if (entry.Value is OpenTelemetryLogger logger) - { - logger.ScopeProvider = scopeProvider; - } - } - } - } - - /// - public ILogger CreateLogger(string categoryName) - { - if (this.loggers[categoryName] is not OpenTelemetryLogger logger) - { - lock (this.loggers) - { - logger = (this.loggers[categoryName] as OpenTelemetryLogger)!; - if (logger == null) - { - logger = new OpenTelemetryLogger(categoryName, this) - { - ScopeProvider = this.ScopeProvider, - }; - - this.loggers[categoryName] = logger; - } - } - } - - return logger; - } - - /// - /// Flushes all the processors registered under , blocks the current thread - /// until flush completed, shutdown signaled or timed out. - /// - /// - /// The number (non-negative) of milliseconds to wait, or - /// Timeout.Infinite to wait indefinitely. - /// - /// - /// Returns true when force flush succeeded; otherwise, false. - /// - /// - /// Thrown when the timeoutMilliseconds is smaller than -1. - /// - /// - /// This function guarantees thread-safety. - /// - internal bool ForceFlush(int timeoutMilliseconds = Timeout.Infinite) - { - OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderForceFlushInvoked(timeoutMilliseconds); - return this.Processor?.ForceFlush(timeoutMilliseconds) ?? true; - } - - /// - /// Add a processor to the . - /// - /// - /// Note: The supplied will be - /// automatically disposed when then the is disposed. - /// - /// Log processor to add. - /// The supplied for chaining. - internal OpenTelemetryLoggerProvider AddProcessor(BaseProcessor processor) - { - OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Started adding processor."); - - Guard.ThrowIfNull(processor); - - processor.SetParentProvider(this); - - StringBuilder processorAdded = new StringBuilder(); - - if (this.threadStaticPool != null && this.ContainsBatchProcessor(processor)) - { - OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Using shared thread pool."); - - this.threadStaticPool = null; - } - - if (this.Processor == null) - { - processorAdded.Append("Setting processor to "); - processorAdded.Append(processor); - - this.Processor = processor; - } - else if (this.Processor is CompositeProcessor compositeProcessor) - { - processorAdded.Append("Adding processor "); - processorAdded.Append(processor); - processorAdded.Append(" to composite processor"); - - compositeProcessor.AddProcessor(processor); - } - else - { - processorAdded.Append("Creating new composite processor with processor "); - processorAdded.Append(this.Processor); - processorAdded.Append(" and adding new processor "); - processorAdded.Append(processor); - - var newCompositeProcessor = new CompositeProcessor(new[] - { - this.Processor, - }); - newCompositeProcessor.SetParentProvider(this); - newCompositeProcessor.AddProcessor(processor); - this.Processor = newCompositeProcessor; - } - - OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent($"Completed adding processor = \"{processorAdded}\"."); - - return this; - } - - internal bool ContainsBatchProcessor(BaseProcessor processor) - { - if (processor is BatchExportProcessor) - { - return true; - } - else if (processor is CompositeProcessor compositeProcessor) - { - var current = compositeProcessor.Head; - while (current != null) - { - if (this.ContainsBatchProcessor(current.Value)) - { - return true; - } - - current = current.Next; - } - } - - return false; - } - - /// - protected override void Dispose(bool disposing) - { - if (!this.disposed) - { - if (disposing) - { - // Wait for up to 5 seconds grace period - this.Processor?.Shutdown(5000); - this.Processor?.Dispose(); - } - - this.disposed = true; - OpenTelemetrySdkEventSource.Log.ProviderDisposed(nameof(OpenTelemetryLoggerProvider)); - } - - base.Dispose(disposing); - } - - private static OpenTelemetryLoggerOptions BuildOptions(Action configure) - { - var options = new OpenTelemetryLoggerOptions(); - configure?.Invoke(options); - return options; - } - } -} diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLoggingExtensions.cs b/src/OpenTelemetry/Logs/OpenTelemetryLoggingExtensions.cs deleted file mode 100644 index 9a2f8607749..00000000000 --- a/src/OpenTelemetry/Logs/OpenTelemetryLoggingExtensions.cs +++ /dev/null @@ -1,73 +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. -// - -#nullable enable - -using System; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Configuration; -using OpenTelemetry.Internal; -using OpenTelemetry.Logs; - -namespace Microsoft.Extensions.Logging -{ - /// - /// Contains extension methods for registering into a instance. - /// - public static class OpenTelemetryLoggingExtensions - { - /// - /// Adds an OpenTelemetry logger named 'OpenTelemetry' to the . - /// - /// - /// Note: This is safe to be called multiple times and by library - /// authors. Only a single - /// will be created for a given . - /// - /// The to use. - /// The supplied for call chaining. - public static ILoggingBuilder AddOpenTelemetry(this ILoggingBuilder builder) - => AddOpenTelemetry(builder, configure: null); - - /// - /// Adds an OpenTelemetry logger named 'OpenTelemetry' to the . - /// - /// - /// The to use. - /// Optional configuration action. - /// The supplied for call chaining. - public static ILoggingBuilder AddOpenTelemetry(this ILoggingBuilder builder, Action? configure) - { - Guard.ThrowIfNull(builder); - - builder.AddConfiguration(); - - builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); - - // Note: This will bind logger options element (eg "Logging:OpenTelemetry") to OpenTelemetryLoggerOptions - LoggerProviderOptions.RegisterProviderOptions(builder.Services); - - if (configure != null) - { - builder.Services.Configure(configure); - } - - return builder; - } - } -} diff --git a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs index 186926a5799..d1dcf6aa765 100644 --- a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs +++ b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs @@ -25,6 +25,11 @@ using OpenTelemetry.Internal; using OpenTelemetry.Resources; +using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper< + OpenTelemetry.Metrics.MeterProviderBuilderSdk, + OpenTelemetry.Metrics.MeterProviderSdk, + OpenTelemetry.Metrics.MeterProviderBuilderState>; + namespace OpenTelemetry.Metrics { /// @@ -50,7 +55,7 @@ internal MeterProviderBuilderBase(MeterProviderBuilderState state) // is bound to an external service collection. internal MeterProviderBuilderBase(IServiceCollection services) { - Guard.ThrowIfNull(services); + Debug.Assert(services != null, "services was null"); services.AddOptions(); services.TryAddSingleton(sp => new MeterProviderSdk(sp, ownsServiceProvider: false)); @@ -100,7 +105,7 @@ MeterProviderBuilder IDeferredMeterProviderBuilder.Configure( else { this.ConfigureServices(services - => MeterProviderBuilderServiceCollectionHelper.RegisterConfigureBuilderCallback(services, configure)); + => CallbackHelper.RegisterConfigureBuilderCallback(services, configure)); } return this; @@ -289,7 +294,8 @@ private MeterProviderBuilder ConfigureState(Action MeterProviderBuilderServiceCollectionHelper.RegisterConfigureStateCallback(services, configure!)); + this.ConfigureServices(services => + CallbackHelper.RegisterConfigureStateCallback(services, configure!)); } return this; diff --git a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs index 5518ae1e9e3..b036335c43d 100644 --- a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs +++ b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs @@ -21,52 +21,38 @@ using System.Diagnostics; using System.Diagnostics.Metrics; using OpenTelemetry.Internal; -using OpenTelemetry.Resources; namespace OpenTelemetry.Metrics { /// /// Stores state used to build a . /// - internal sealed class MeterProviderBuilderState + internal sealed class MeterProviderBuilderState : ProviderBuilderState { - internal const int MaxMetricsDefault = 1000; - internal const int MaxMetricPointsPerMetricDefault = 2000; - internal readonly IServiceProvider ServiceProvider; - internal readonly List Instrumentation = new(); - internal readonly List Readers = new(); - internal readonly List MeterSources = new(); - internal readonly List> ViewConfigs = new(); - internal ResourceBuilder? ResourceBuilder; - internal int MaxMetricStreams = MaxMetricsDefault; - internal int MaxMetricPointsPerMetricStream = MaxMetricPointsPerMetricDefault; + public const int MaxMetricsDefault = 1000; + public const int MaxMetricPointsPerMetricDefault = 2000; private MeterProviderBuilderSdk? builder; - public MeterProviderBuilderState(IServiceProvider serviceProvider) + public MeterProviderBuilderState( + IServiceProvider serviceProvider, + MeterProviderSdk provider) + : base(serviceProvider, provider) { - Debug.Assert(serviceProvider != null, "serviceProvider was null"); - - this.ServiceProvider = serviceProvider!; } - public MeterProviderBuilderSdk Builder => this.builder ??= new MeterProviderBuilderSdk(this); + public override MeterProviderBuilderSdk Builder + => this.builder ??= new MeterProviderBuilderSdk(this); - public void AddInstrumentation( - string instrumentationName, - string instrumentationVersion, - object instrumentation) - { - Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace"); - Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace"); - Debug.Assert(instrumentation != null, "instrumentation was null"); - - this.Instrumentation.Add( - new InstrumentationRegistration( - instrumentationName, - instrumentationVersion, - instrumentation!)); - } + public List Readers { get; } = new(); + + public List MeterSources { get; } = new(); + + public List> ViewConfigs { get; } = new(); + + public int MaxMetricStreams { get; set; } = MaxMetricsDefault; + + public int MaxMetricPointsPerMetricStream { get; set; } = MaxMetricPointsPerMetricDefault; public void AddMeter(params string[] names) { @@ -93,35 +79,5 @@ public void AddView(Func viewConfig) this.ViewConfigs.Add(viewConfig!); } - - public void ConfigureResource(Action configure) - { - Debug.Assert(configure != null, "configure was null"); - - var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault(); - - configure!(resourceBuilder); - } - - public void SetResourceBuilder(ResourceBuilder resourceBuilder) - { - Debug.Assert(resourceBuilder != null, "resourceBuilder was null"); - - this.ResourceBuilder = resourceBuilder; - } - - internal readonly struct InstrumentationRegistration - { - public readonly string Name; - public readonly string Version; - public readonly object Instance; - - internal InstrumentationRegistration(string name, string version, object instance) - { - this.Name = name; - this.Version = version; - this.Instance = instance; - } - } } } diff --git a/src/OpenTelemetry/Metrics/MeterProviderSdk.cs b/src/OpenTelemetry/Metrics/MeterProviderSdk.cs index 223290a210e..4cd76444f75 100644 --- a/src/OpenTelemetry/Metrics/MeterProviderSdk.cs +++ b/src/OpenTelemetry/Metrics/MeterProviderSdk.cs @@ -25,6 +25,11 @@ using OpenTelemetry.Internal; using OpenTelemetry.Resources; +using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper< + OpenTelemetry.Metrics.MeterProviderBuilderSdk, + OpenTelemetry.Metrics.MeterProviderSdk, + OpenTelemetry.Metrics.MeterProviderBuilderState>; + namespace OpenTelemetry.Metrics { internal sealed class MeterProviderSdk : MeterProvider @@ -52,9 +57,9 @@ internal MeterProviderSdk( OpenTelemetrySdkEventSource.Log.MeterProviderSdkEvent("Building MeterProvider."); - var state = new MeterProviderBuilderState(serviceProvider); + var state = new MeterProviderBuilderState(serviceProvider, this); - MeterProviderBuilderServiceCollectionHelper.InvokeRegisteredConfigureStateCallbacks( + CallbackHelper.InvokeRegisteredConfigureStateCallbacks( serviceProvider, state); diff --git a/src/OpenTelemetry/ProviderExtensions.cs b/src/OpenTelemetry/ProviderExtensions.cs index 1ae3a85ecfc..bfefeb09b55 100644 --- a/src/OpenTelemetry/ProviderExtensions.cs +++ b/src/OpenTelemetry/ProviderExtensions.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; @@ -38,14 +40,18 @@ public static Resource GetResource(this BaseProvider baseProvider) { return tracerProviderSdk.Resource; } - else if (baseProvider is OpenTelemetryLoggerProvider otelLoggerProvider) + else if (baseProvider is LoggerProviderSdk loggerProviderSdk) { - return otelLoggerProvider.Resource; + return loggerProviderSdk.Resource; } else if (baseProvider is MeterProviderSdk meterProviderSdk) { return meterProviderSdk.Resource; } + else if (baseProvider is OpenTelemetryLoggerProvider iLoggerProvider) + { + return iLoggerProvider.Provider.GetResource(); + } return Resource.Empty; } @@ -60,7 +66,7 @@ public static Resource GetDefaultResource(this BaseProvider baseProvider) return ResourceBuilder.CreateDefault().Build(); } - internal static Action GetObservableInstrumentCollectCallback(this BaseProvider baseProvider) + internal static Action? GetObservableInstrumentCollectCallback(this BaseProvider baseProvider) { if (baseProvider is MeterProviderSdk meterProviderSdk) { diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index 62fb0da26d1..7a9825f05a9 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -19,6 +19,7 @@ using System.Diagnostics; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Internal; +using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Trace; @@ -58,6 +59,20 @@ public static void SetDefaultTextMapPropagator(TextMapPropagator textMapPropagat Propagators.DefaultTextMapPropagator = textMapPropagator; } + /// + /// Creates a which is used to build + /// an . In a typical application, a single + /// is created at application startup and + /// disposed at application shutdown. It is important to ensure that the + /// provider is not disposed too early. + /// + /// instance, which is used + /// to build a . + public static LoggerProviderBuilder CreateLoggerProviderBuilder() + { + return new LoggerProviderBuilderSdk(); + } + /// /// Creates a which is used to build /// a . In a typical application, a single diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs index a747395308c..cfb0c28fb8a 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs @@ -24,6 +24,11 @@ using OpenTelemetry.Internal; using OpenTelemetry.Resources; +using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper< + OpenTelemetry.Trace.TracerProviderBuilderSdk, + OpenTelemetry.Trace.TracerProviderSdk, + OpenTelemetry.Trace.TracerProviderBuilderState>; + namespace OpenTelemetry.Trace { /// @@ -49,7 +54,7 @@ internal TracerProviderBuilderBase(TracerProviderBuilderState state) // is bound to an external service collection. internal TracerProviderBuilderBase(IServiceCollection services) { - Guard.ThrowIfNull(services); + Debug.Assert(services != null, "services was null"); services.AddOptions(); services.TryAddSingleton(sp => new TracerProviderSdk(sp, ownsServiceProvider: false)); @@ -109,7 +114,7 @@ TracerProviderBuilder IDeferredTracerProviderBuilder.Configure( else { this.ConfigureServices(services - => TracerProviderBuilderServiceCollectionHelper.RegisterConfigureBuilderCallback(services, configure)); + => CallbackHelper.RegisterConfigureBuilderCallback(services, configure)); } return this; @@ -324,7 +329,8 @@ private TracerProviderBuilder ConfigureState(Action TracerProviderBuilderServiceCollectionHelper.RegisterConfigureStateCallback(services, configure!)); + this.ConfigureServices(services => + CallbackHelper.RegisterConfigureStateCallback(services, configure!)); } return this; diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderServiceCollectionHelper.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderServiceCollectionHelper.cs deleted file mode 100644 index ae68e0881b5..00000000000 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderServiceCollectionHelper.cs +++ /dev/null @@ -1,81 +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. -// - -#nullable enable - -using System; -using System.Diagnostics; -using Microsoft.Extensions.DependencyInjection; - -namespace OpenTelemetry.Trace; - -internal static class TracerProviderBuilderServiceCollectionHelper -{ - internal static IServiceCollection RegisterConfigureBuilderCallback( - IServiceCollection services, - Action configure) - { - Debug.Assert(configure != null, "configure was null"); - - return RegisterConfigureStateCallback( - services, - (sp, state) => configure!(sp, state.Builder)); - } - - internal static IServiceCollection RegisterConfigureStateCallback( - IServiceCollection services, - Action configure) - { - Debug.Assert(services != null, "services was null"); - Debug.Assert(configure != null, "configure was null"); - - return services.AddSingleton(new ConfigureTracerProviderBuilderStateCallbackRegistration(configure!)); - } - - internal static void InvokeRegisteredConfigureStateCallbacks( - IServiceProvider serviceProvider, - TracerProviderBuilderState state) - { - Debug.Assert(serviceProvider != null, "serviceProvider was null"); - Debug.Assert(state != null, "state was null"); - - var callbackRegistrations = serviceProvider.GetServices(); - - foreach (var callbackRegistration in callbackRegistrations) - { - callbackRegistration.Configure(serviceProvider!, state!); - } - } - - private sealed class ConfigureTracerProviderBuilderStateCallbackRegistration - { - private readonly Action configure; - - public ConfigureTracerProviderBuilderStateCallbackRegistration( - Action configure) - { - this.configure = configure; - } - - public void Configure(IServiceProvider serviceProvider, TracerProviderBuilderState state) - { - Debug.Assert(serviceProvider != null, "serviceProvider was null"); - Debug.Assert(state != null, "state was null"); - - this.configure(serviceProvider!, state!); - } - } -} diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs index 0f6be92701a..bb0629c1839 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs @@ -20,50 +20,35 @@ using System.Collections.Generic; using System.Diagnostics; using OpenTelemetry.Internal; -using OpenTelemetry.Resources; namespace OpenTelemetry.Trace { /// /// Stores state used to build a . /// - internal sealed class TracerProviderBuilderState + internal sealed class TracerProviderBuilderState : ProviderBuilderState { - internal readonly IServiceProvider ServiceProvider; - internal readonly List Instrumentation = new(); - internal readonly List> Processors = new(); - internal readonly List Sources = new(); - internal readonly HashSet LegacyActivityOperationNames = new(StringComparer.OrdinalIgnoreCase); - internal ResourceBuilder? ResourceBuilder; - internal Sampler? Sampler; - internal bool SetErrorStatusOnException; - private TracerProviderBuilderSdk? builder; - public TracerProviderBuilderState(IServiceProvider serviceProvider) + public TracerProviderBuilderState( + IServiceProvider serviceProvider, + TracerProviderSdk provider) + : base(serviceProvider, provider) { - Debug.Assert(serviceProvider != null, "serviceProvider was null"); - - this.ServiceProvider = serviceProvider!; } - public TracerProviderBuilderSdk Builder => this.builder ??= new TracerProviderBuilderSdk(this); + public override TracerProviderBuilderSdk Builder + => this.builder ??= new TracerProviderBuilderSdk(this); - public void AddInstrumentation( - string instrumentationName, - string instrumentationVersion, - object instrumentation) - { - Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace"); - Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace"); - Debug.Assert(instrumentation != null, "instrumentation was null"); - - this.Instrumentation.Add( - new InstrumentationRegistration( - instrumentationName, - instrumentationVersion, - instrumentation!)); - } + public List> Processors { get; } = new(); + + public List Sources { get; } = new(); + + public HashSet LegacyActivityOperationNames { get; } = new(StringComparer.OrdinalIgnoreCase); + + public Sampler? Sampler { get; private set; } + + public bool SetErrorStatusOnException { get; set; } public void AddLegacySource(string operationName) { @@ -93,22 +78,6 @@ public void AddSource(params string[] names) } } - public void ConfigureResource(Action configure) - { - Debug.Assert(configure != null, "configure was null"); - - var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault(); - - configure!(resourceBuilder); - } - - public void SetResourceBuilder(ResourceBuilder resourceBuilder) - { - Debug.Assert(resourceBuilder != null, "resourceBuilder was null"); - - this.ResourceBuilder = resourceBuilder; - } - public void SetSampler(Sampler sampler) { Debug.Assert(sampler != null, "sampler was null"); @@ -127,19 +96,5 @@ internal void EnableErrorStatusOnException() throw new NotSupportedException($"'{nameof(TracerProviderBuilderExtensions.SetErrorStatusOnException)}' is not supported on this platform", ex); } } - - internal readonly struct InstrumentationRegistration - { - public readonly string Name; - public readonly string Version; - public readonly object Instance; - - internal InstrumentationRegistration(string name, string version, object instance) - { - this.Name = name; - this.Version = version; - this.Instance = instance; - } - } } } diff --git a/src/OpenTelemetry/Trace/TracerProviderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderSdk.cs index 13d3d969cb0..280680e1372 100644 --- a/src/OpenTelemetry/Trace/TracerProviderSdk.cs +++ b/src/OpenTelemetry/Trace/TracerProviderSdk.cs @@ -24,6 +24,11 @@ using OpenTelemetry.Internal; using OpenTelemetry.Resources; +using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper< + OpenTelemetry.Trace.TracerProviderBuilderSdk, + OpenTelemetry.Trace.TracerProviderSdk, + OpenTelemetry.Trace.TracerProviderBuilderState>; + namespace OpenTelemetry.Trace { internal sealed class TracerProviderSdk : TracerProvider @@ -49,9 +54,9 @@ internal TracerProviderSdk( Debug.Assert(this.OwnedServiceProvider != null, "serviceProvider was not IDisposable"); } - var state = new TracerProviderBuilderState(serviceProvider); + var state = new TracerProviderBuilderState(serviceProvider, this); - TracerProviderBuilderServiceCollectionHelper.InvokeRegisteredConfigureStateCallbacks( + CallbackHelper.InvokeRegisteredConfigureStateCallbacks( serviceProvider, state); diff --git a/test/Benchmarks/Logs/LogBenchmarks.cs b/test/Benchmarks/Logs/LogBenchmarks.cs index 796cc722555..36c8c370a9a 100644 --- a/test/Benchmarks/Logs/LogBenchmarks.cs +++ b/test/Benchmarks/Logs/LogBenchmarks.cs @@ -55,25 +55,24 @@ public LogBenchmarks() var loggerFactoryWithOneProcessor = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => options - .AddProcessor(new DummyLogProcessor())); + builder.AddOpenTelemetry().AddProcessor(new DummyLogProcessor()); }); this.loggerWithOneProcessor = loggerFactoryWithOneProcessor.CreateLogger(); var loggerFactoryWithTwoProcessor = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => options + builder.AddOpenTelemetry() .AddProcessor(new DummyLogProcessor()) - .AddProcessor(new DummyLogProcessor())); + .AddProcessor(new DummyLogProcessor()); }); this.loggerWithTwoProcessors = loggerFactoryWithTwoProcessor.CreateLogger(); var loggerFactoryWithThreeProcessor = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => options + builder.AddOpenTelemetry() .AddProcessor(new DummyLogProcessor()) .AddProcessor(new DummyLogProcessor()) - .AddProcessor(new DummyLogProcessor())); + .AddProcessor(new DummyLogProcessor()); }); this.loggerWithThreeProcessors = loggerFactoryWithThreeProcessor.CreateLogger(); } diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs index 8feab03e185..85993b5c656 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs @@ -33,84 +33,136 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests public class OtlpLogExporterTests : Http2UnencryptedSupportTests { [Fact] - public void AddOtlpLogExporterOptionsTest() + public void AddOtlpLogExporterReceivesAttributesWithParseStateValueSetToFalse() { - AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); - var loggerOptions = new OpenTelemetryLoggerOptions(); - Assert.False(loggerOptions.ParseStateValues); - loggerOptions.AddOtlpExporter(); - Assert.True(loggerOptions.ParseStateValues); - } + bool optionsValidated = false; - [Fact] - public void AddOtlpLogExporterSetsParseStateValueToTrue() - { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - options.AddOtlpExporter(); - }); + builder + .AddOpenTelemetry() + .ConfigureServices(services => services.Configure(o => + { + optionsValidated = true; + Assert.True(o.IncludeState); + Assert.False(o.ParseStateValues); + })) + .AddInMemoryExporter(logRecords) + .AddOtlpExporter(); }); + Assert.True(optionsValidated); + var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99); Assert.Single(logRecords); var logRecord = logRecords[0]; +#pragma warning disable CS0618 // Type or member is obsolete Assert.Null(logRecord.State); - Assert.NotNull(logRecord.StateValues); +#pragma warning restore CS0618 // Type or member is obsolete + Assert.NotNull(logRecord.Attributes); } - [Fact] - public void AddOtlpLogExporterParseStateValueCanBeTurnedOff() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void AddOtlpLogExporterParseStateValueCanBeTurnedOff(bool parseState) { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - options.AddOtlpExporter(); - options.ParseStateValues = false; - }); + builder + .AddOpenTelemetry(options => options.ParseStateValues = parseState) + .AddInMemoryExporter(logRecords) + .AddOtlpExporter(); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); - logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99); + logger.Log(LogLevel.Information, default, new { propertyA = "valueA" }, null, (s, e) => "Custom state log message"); Assert.Single(logRecords); + var logRecord = logRecords[0]; - Assert.NotNull(logRecord.State); - Assert.Null(logRecord.StateValues); + +#pragma warning disable CS0618 // Type or member is obsolete + if (parseState) + { + Assert.Null(logRecord.State); + Assert.NotNull(logRecord.Attributes); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "propertyA" && (string)kvp.Value == "valueA"); + } + else + { + Assert.NotNull(logRecord.State); + Assert.Null(logRecord.Attributes); + } +#pragma warning restore CS0618 // Type or member is obsolete } - [Fact] - public void AddOtlpLogExporterParseStateValueCanBeTurnedOffHosting() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void AddOtlpLogExporterParseStateValueCanBeTurnedOffHosting(bool parseState) { var logRecords = new List(); AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); var hostBuilder = new HostBuilder(); - hostBuilder.ConfigureLogging(logging => logging.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - options.AddOtlpExporter(); - })); + hostBuilder.ConfigureLogging(logging => logging + .AddOpenTelemetry() + .AddInMemoryExporter(logRecords) + .AddOtlpExporter()); hostBuilder.ConfigureServices(services => - services.Configure(options => options.ParseStateValues = false)); + services.Configure(options => options.ParseStateValues = parseState)); var host = hostBuilder.Build(); var loggerFactory = host.Services.GetService(); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); - logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99); + logger.Log(LogLevel.Information, default, new { propertyA = "valueA" }, null, (s, e) => "Custom state log message"); Assert.Single(logRecords); + var logRecord = logRecords[0]; - Assert.NotNull(logRecord.State); - Assert.Null(logRecord.StateValues); + +#pragma warning disable CS0618 // Type or member is obsolete + if (parseState) + { + Assert.Null(logRecord.State); + Assert.NotNull(logRecord.Attributes); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "propertyA" && (string)kvp.Value == "valueA"); + } + else + { + Assert.NotNull(logRecord.State); + Assert.Null(logRecord.Attributes); + } +#pragma warning restore CS0618 // Type or member is obsolete + } + + [Fact] + public void AddOtlpLogExporterNamedOptionsSupported() + { + int defaultExporterOptionsConfigureOptionsInvocations = 0; + int namedExporterOptionsConfigureOptionsInvocations = 0; + + using var loggerFactory = LoggerFactory.Create(builder => + { + builder + .AddOpenTelemetry() + .ConfigureServices(services => + { + services.Configure(o => defaultExporterOptionsConfigureOptionsInvocations++); + + services.Configure("Exporter2", o => namedExporterOptionsConfigureOptionsInvocations++); + }) + .AddOtlpExporter() + .AddOtlpExporter("Exporter2", o => { }); + }); + + Assert.Equal(1, defaultExporterOptionsConfigureOptionsInvocations); + Assert.Equal(1, namedExporterOptionsConfigureOptionsInvocations); } [Fact] @@ -119,12 +171,13 @@ public void OtlpLogRecordTestWhenStateValuesArePopulated() var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.IncludeFormattedMessage = true; - options.ParseStateValues = true; - options.AddInMemoryExporter(logRecords); - }); + builder + .AddOpenTelemetry(options => + { + options.IncludeFormattedMessage = true; + options.ParseStateValues = true; + }) + .AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); @@ -162,10 +215,7 @@ public void CheckToOtlpLogRecordLoggerCategory() var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - }); + builder.AddOpenTelemetry().AddInMemoryExporter(logRecords); }); var logger1 = loggerFactory.CreateLogger("CategoryA"); @@ -198,12 +248,13 @@ public void CheckToOtlpLogRecordEventId() var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.IncludeFormattedMessage = true; - options.ParseStateValues = true; - options.AddInMemoryExporter(logRecords); - }); + builder + .AddOpenTelemetry(options => + { + options.IncludeFormattedMessage = true; + options.ParseStateValues = true; + }) + .AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); @@ -247,10 +298,7 @@ public void CheckToOtlpLogRecordTraceIdSpanIdFlagWithNoActivity() var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - }); + builder.AddOpenTelemetry().AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); @@ -270,10 +318,7 @@ public void CheckToOtlpLogRecordSpanIdTraceIdAndFlag() var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - }); + builder.AddOpenTelemetry().AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); @@ -308,12 +353,9 @@ public void CheckToOtlpLogRecordSeverityLevelAndText(LogLevel logLevel) var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - options.IncludeFormattedMessage = true; - }) - .AddFilter("CheckToOtlpLogRecordSeverityLevelAndText", LogLevel.Trace); + builder + .AddFilter("CheckToOtlpLogRecordSeverityLevelAndText", LogLevel.Trace) + .AddOpenTelemetry(options => options.IncludeFormattedMessage = true).AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("CheckToOtlpLogRecordSeverityLevelAndText"); @@ -324,7 +366,7 @@ public void CheckToOtlpLogRecordSeverityLevelAndText(LogLevel logLevel) var otlpLogRecord = logRecord.ToOtlpLog(); Assert.NotNull(otlpLogRecord); - Assert.Equal(logRecord.LogLevel.ToString(), otlpLogRecord.SeverityText); + Assert.Equal(logRecord.Severity.ToString(), otlpLogRecord.SeverityText); switch (logLevel) { case LogLevel.Trace: @@ -356,12 +398,13 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - options.IncludeFormattedMessage = includeFormattedMessage; - options.ParseStateValues = true; - }); + builder + .AddOpenTelemetry(options => + { + options.IncludeFormattedMessage = includeFormattedMessage; + options.ParseStateValues = true; + }) + .AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); @@ -393,14 +436,10 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) otlpLogRecord = logRecord.ToOtlpLog(); Assert.NotNull(otlpLogRecord); - if (includeFormattedMessage) - { - Assert.Equal(logRecord.FormattedMessage, otlpLogRecord.Body.StringValue); - } - else - { - Assert.Null(otlpLogRecord.Body); - } + + // Formatter is always called if no template can be found. + Assert.Equal(logRecord.FormattedMessage, otlpLogRecord.Body.StringValue); + Assert.Equal(logRecord.Body, otlpLogRecord.Body.StringValue); logRecords.Clear(); @@ -416,14 +455,7 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) // There is no formatter, so no way to populate Body. // Exporter won't even attempt to do ToString() on State. - if (includeFormattedMessage) - { - Assert.Null(otlpLogRecord.Body); - } - else - { - Assert.Null(otlpLogRecord.Body); - } + Assert.Null(otlpLogRecord.Body); } [Fact] @@ -432,10 +464,7 @@ public void CheckToOtlpLogRecordExceptionAttributes() var logRecords = new List(); using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddInMemoryExporter(logRecords); - }); + builder.AddOpenTelemetry().AddInMemoryExporter(logRecords); }); var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); diff --git a/test/OpenTelemetry.Extensions.EventSource.Tests/AssemblyInfo.cs b/test/OpenTelemetry.Extensions.EventSource.Tests/AssemblyInfo.cs new file mode 100644 index 00000000000..11bfd5a2025 --- /dev/null +++ b/test/OpenTelemetry.Extensions.EventSource.Tests/AssemblyInfo.cs @@ -0,0 +1,19 @@ +// +// 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; + +[assembly: CLSCompliant(false)] diff --git a/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetry.Extensions.EventSource.Tests.csproj b/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetry.Extensions.EventSource.Tests.csproj new file mode 100644 index 00000000000..855502dd5b3 --- /dev/null +++ b/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetry.Extensions.EventSource.Tests.csproj @@ -0,0 +1,27 @@ + + + Unit test project for OpenTelemetry EventSource extensions + + net6.0 + $(TargetFrameworks);net462 + enable + AllEnabledByDefault + latest + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + diff --git a/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetryEventSourceLogEmitterTests.cs b/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetryEventSourceLogEmitterTests.cs new file mode 100644 index 00000000000..a521bd46a52 --- /dev/null +++ b/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetryEventSourceLogEmitterTests.cs @@ -0,0 +1,331 @@ +// +// 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.Diagnostics.Tracing; +using System.Globalization; +using OpenTelemetry.Logs; +using Xunit; + +namespace OpenTelemetry.Extensions.EventSource.Tests +{ + public class OpenTelemetryEventSourceLogEmitterTests + { + [Theory] + [InlineData(true)] + [InlineData(false)] + public void OpenTelemetryEventSourceLogEmitterDisposesProviderTests(bool dispose) + { +#pragma warning disable CA2000 // Dispose objects before losing scope + var disposeTrackingProcessor = new DisposeTrackingProcessor(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(disposeTrackingProcessor) + .Build()) + { + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => null, + disposeProvider: dispose)) + { + } + + Assert.Equal(dispose, disposeTrackingProcessor.Disposed); + + openTelemetryLoggerProvider.Dispose(); + } + + Assert.True(disposeTrackingProcessor.Disposed); + } + + [Theory] + [InlineData(TestEventSource.EventSourceName, EventLevel.LogAlways, 2)] + [InlineData(TestEventSource.EventSourceName, EventLevel.Warning, 1)] + [InlineData("_invalid_", EventLevel.LogAlways, 0)] + public void OpenTelemetryEventSourceLogEmitterFilterTests(string sourceName, EventLevel? eventLevel, int expectedNumberOfLogRecords) + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => name == sourceName ? eventLevel : null)) + { + TestEventSource.Log.SimpleEvent(); + TestEventSource.Log.ComplexEvent("Test_Message", 18); + } + + Assert.Equal(expectedNumberOfLogRecords, exportedItems.Count); + } + + [Fact] + public void OpenTelemetryEventSourceLogEmitterCapturesExistingSourceTest() + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + TestEventSource.Log.SimpleEvent(); + + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null)) + { + TestEventSource.Log.SimpleEvent(); + } + + Assert.Single(exportedItems); + } + + [Fact] + public void OpenTelemetryEventSourceLogEmitterSimpleEventTest() + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null)) + { + TestEventSource.Log.SimpleEvent(); + } + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp); + Assert.Null(logRecord.FormattedMessage); + Assert.Equal(TestEventSource.SimpleEventMessage, logRecord.Body); + Assert.Equal(default, logRecord.EventId); + Assert.Equal(LogRecordSeverity.Warning, logRecord.Severity); + Assert.Null(logRecord.CategoryName); + Assert.Null(logRecord.Exception); + + Assert.Equal(default, logRecord.TraceId); + Assert.Equal(default, logRecord.SpanId); + Assert.Null(logRecord.TraceState); + Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags); + + Assert.NotNull(logRecord.Attributes); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.name" && (string?)kvp.Value == TestEventSource.EventSourceName); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.event_id" && (int?)kvp.Value == TestEventSource.SimpleEventId); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.event_name" && (string?)kvp.Value == nameof(TestEventSource.SimpleEvent)); + } + + [Fact] + public void OpenTelemetryEventSourceLogEmitterSimpleEventWithActivityTest() + { + using var activity = new Activity("Test"); + activity.Start(); + + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null)) + { + TestEventSource.Log.SimpleEvent(); + } + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotEqual(default, logRecord.TraceId); + + Assert.Equal(activity.TraceId, logRecord.TraceId); + Assert.Equal(activity.SpanId, logRecord.SpanId); + Assert.Equal(activity.TraceStateString, logRecord.TraceState); + Assert.Equal(activity.ActivityTraceFlags, logRecord.TraceFlags); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void OpenTelemetryEventSourceLogEmitterComplexEventTest(bool formatMessage) + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + openTelemetryLoggerProvider, + (name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null, + options: new() { IncludeFormattedMessage = formatMessage })) + { + TestEventSource.Log.ComplexEvent("Test_Message", 18); + } + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp); + + Assert.Equal(TestEventSource.ComplexEventMessageStructured, logRecord.Body); + Assert.Null(logRecord.FormattedMessage); + + Assert.Equal(default, logRecord.EventId); + Assert.Equal(LogRecordSeverity.Information, logRecord.Severity); + Assert.Null(logRecord.CategoryName); + Assert.Null(logRecord.Exception); + + Assert.Equal(default, logRecord.TraceId); + Assert.Equal(default, logRecord.SpanId); + Assert.Null(logRecord.TraceState); + Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags); + + Assert.NotNull(logRecord.Attributes); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.name" && (string?)kvp.Value == TestEventSource.EventSourceName); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "arg1" && (string?)kvp.Value == "Test_Message"); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "arg2" && (int?)kvp.Value == 18); + + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.event_id" && (int?)kvp.Value == TestEventSource.ComplexEventId); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.event_name" && (string?)kvp.Value == nameof(TestEventSource.ComplexEvent)); + + if (formatMessage) + { + string expectedMessage = string.Format(CultureInfo.InvariantCulture, TestEventSource.ComplexEventMessage, "Test_Message", 18); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.formatted_message" && (string?)kvp.Value == expectedMessage); + } + } + + [Theory(Skip = "Not runnable in CI, see note.")] + [InlineData(true)] + [InlineData(false)] + public void OpenTelemetryEventSourceLogEmitterActivityIdTest(bool enableTplListener) + { + /* + * Note: + * + * To enable Activity ID the 'System.Threading.Tasks.TplEventSource' + * source must be enabled see: + * https://docs.microsoft.com/en-us/dotnet/core/diagnostics/eventsource-activity-ids#tracking-work-using-an-activity-id + * + * Once enabled, it cannot be turned off: + * https://github.com/dotnet/runtime/blob/0fbdb1ed6e076829e4693a61ae5d11c4cb23e7ee/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/ActivityTracker.cs#L208 + * + * That behavior makes testing it difficult. + */ + using var tplListener = enableTplListener ? new TplEventSourceListener() : null; + + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter( + loggerProvider, + (name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null)) + { + TestEventSource.Log.WorkStart(); + + TestEventSource.Log.SubworkStart(); + + TestEventSource.Log.SubworkStop(); + + TestEventSource.Log.WorkStop(); + } + + Assert.Equal(4, exportedItems.Count); + + var logRecord = exportedItems[1]; + Assert.NotNull(logRecord.Attributes); + if (enableTplListener) + { + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.activity_id"); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "event_source.related_activity_id"); + } + else + { + Assert.DoesNotContain(logRecord.Attributes, kvp => kvp.Key == "event_source.activity_id"); + Assert.DoesNotContain(logRecord.Attributes, kvp => kvp.Key == "event_source.related_activity_id"); + } + } + + private sealed class DisposeTrackingProcessor : BaseProcessor + { + public bool Disposed { get; private set; } + + protected override void Dispose(bool disposing) + { + this.Disposed = true; + + base.Dispose(disposing); + } + } + + private sealed class TplEventSourceListener : EventListener + { + private readonly List eventSources = new(); + + /// + public override void Dispose() + { + foreach (System.Diagnostics.Tracing.EventSource eventSource in this.eventSources) + { + this.DisableEvents(eventSource); + } + + this.eventSources.Clear(); + + base.Dispose(); + } + + protected override void OnEventSourceCreated(System.Diagnostics.Tracing.EventSource eventSource) + { + if (eventSource.Name == "System.Threading.Tasks.TplEventSource") + { + // Activity IDs aren't enabled by default. + // Enabling Keyword 0x80 on the TplEventSource turns them on + this.EnableEvents(eventSource, EventLevel.LogAlways, (EventKeywords)0x80); + this.eventSources.Add(eventSource); + } + } + } + } +} diff --git a/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetryEventSourceLoggerOptionsExtensionsTests.cs b/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetryEventSourceLoggerOptionsExtensionsTests.cs new file mode 100644 index 00000000000..eb9c805468a --- /dev/null +++ b/test/OpenTelemetry.Extensions.EventSource.Tests/OpenTelemetryEventSourceLoggerOptionsExtensionsTests.cs @@ -0,0 +1,55 @@ +// +// 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. +// + +#nullable enable + +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using OpenTelemetry.Logs; +using Xunit; + +namespace OpenTelemetry.Extensions.EventSource.Tests +{ + public class OpenTelemetryEventSourceLoggerOptionsExtensionsTests + { + [Fact] + public void AddOpenTelemetryEventSourceLogEmitterTest() + { + var exportedItems = new List(); + + var services = new ServiceCollection(); + + services.AddLogging(builder => + { + builder + .AddOpenTelemetry() + .AddInMemoryExporter(exportedItems) + .AddEventSourceLogEmitter((name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null); + }); + + using (var serviceProvider = services.BuildServiceProvider()) + { + var loggerFactory = serviceProvider.GetRequiredService(); + + TestEventSource.Log.SimpleEvent(); + } + + Assert.Single(exportedItems); + } + } +} diff --git a/test/OpenTelemetry.Extensions.EventSource.Tests/TestEventSource.cs b/test/OpenTelemetry.Extensions.EventSource.Tests/TestEventSource.cs new file mode 100644 index 00000000000..aee8f12b888 --- /dev/null +++ b/test/OpenTelemetry.Extensions.EventSource.Tests/TestEventSource.cs @@ -0,0 +1,71 @@ +// +// 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.Diagnostics.Tracing; + +namespace OpenTelemetry.Extensions.EventSource.Tests +{ + [EventSource(Name = TestEventSource.EventSourceName)] + public sealed class TestEventSource : System.Diagnostics.Tracing.EventSource + { + public const string EventSourceName = "OpenTelemetry.Extensions.EventSource.Tests"; + + public const int SimpleEventId = 1; + public const string SimpleEventMessage = "Warning event with no arguments."; + + public const int ComplexEventId = 2; + public const string ComplexEventMessage = "Information event with two arguments: '{0}' & '{1}'."; + public const string ComplexEventMessageStructured = "Information event with two arguments: '{arg1}' & '{arg2}'."; + + public static TestEventSource Log { get; } = new(); + + [Event(SimpleEventId, Message = SimpleEventMessage, Level = EventLevel.Warning)] + public void SimpleEvent() + { + this.WriteEvent(SimpleEventId); + } + + [Event(ComplexEventId, Message = ComplexEventMessage, Level = EventLevel.Informational)] + public void ComplexEvent(string arg1, int arg2) + { + this.WriteEvent(ComplexEventId, arg1, arg2); + } + + [Event(3, Level = EventLevel.Verbose)] + public void WorkStart() + { + this.WriteEvent(3); + } + + [Event(4, Level = EventLevel.Verbose)] + public void WorkStop() + { + this.WriteEvent(4); + } + + [Event(5, Level = EventLevel.Verbose)] + public void SubworkStart() + { + this.WriteEvent(5); + } + + [Event(6, Level = EventLevel.Verbose)] + public void SubworkStop() + { + this.WriteEvent(6); + } + } +} diff --git a/test/OpenTelemetry.Extensions.Serilog.Tests/AssemblyInfo.cs b/test/OpenTelemetry.Extensions.Serilog.Tests/AssemblyInfo.cs new file mode 100644 index 00000000000..11bfd5a2025 --- /dev/null +++ b/test/OpenTelemetry.Extensions.Serilog.Tests/AssemblyInfo.cs @@ -0,0 +1,19 @@ +// +// 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; + +[assembly: CLSCompliant(false)] diff --git a/test/OpenTelemetry.Extensions.Serilog.Tests/OpenTelemetry.Extensions.Serilog.Tests.csproj b/test/OpenTelemetry.Extensions.Serilog.Tests/OpenTelemetry.Extensions.Serilog.Tests.csproj new file mode 100644 index 00000000000..0dac46ccfe2 --- /dev/null +++ b/test/OpenTelemetry.Extensions.Serilog.Tests/OpenTelemetry.Extensions.Serilog.Tests.csproj @@ -0,0 +1,32 @@ + + + Unit test project for OpenTelemetry Serilog extensions + + net6.0 + $(TargetFrameworks);net462 + enable + AllEnabledByDefault + latest + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + diff --git a/test/OpenTelemetry.Extensions.Serilog.Tests/OpenTelemetrySerilogSinkTests.cs b/test/OpenTelemetry.Extensions.Serilog.Tests/OpenTelemetrySerilogSinkTests.cs new file mode 100644 index 00000000000..036873f4944 --- /dev/null +++ b/test/OpenTelemetry.Extensions.Serilog.Tests/OpenTelemetrySerilogSinkTests.cs @@ -0,0 +1,303 @@ +// +// 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.Internal; +using OpenTelemetry.Logs; +using OpenTelemetry.Trace; +using Serilog; +using Xunit; +using ILogger = Serilog.ILogger; + +namespace OpenTelemetry.Extensions.Serilog.Tests +{ + public class OpenTelemetrySerilogSinkTests + { + [Theory] + [InlineData(true)] + [InlineData(false)] + public void SerilogDisposesProviderTests(bool dispose) + { +#pragma warning disable CA2000 // Dispose objects before losing scope + var disposeTrackingProcessor = new DisposeTrackingProcessor(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + using (var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(disposeTrackingProcessor) + .Build()) + { + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(loggerProvider, disposeProvider: dispose) + .CreateLogger(); + + Log.CloseAndFlush(); + + Assert.Equal(dispose, disposeTrackingProcessor.Disposed); + } + + Assert.True(disposeTrackingProcessor.Disposed); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void SerilogBasicLogTests(bool includeRenderedMessage) + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry( + loggerProvider, + options: new() { IncludeRenderedMessage = includeRenderedMessage }, + disposeProvider: true) + .CreateLogger(); + + Log.Logger.Information("Hello {greeting}", "World"); + + Log.CloseAndFlush(); + + Assert.Single(exportedItems); + + LogRecord logRecord = exportedItems[0]; + + Assert.Equal("Hello {greeting}", logRecord.Body); + + Assert.Null(logRecord.FormattedMessage); + + Assert.NotNull(logRecord.Attributes); + + if (!includeRenderedMessage) + { + Assert.Single(logRecord.Attributes); + } + else + { + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "serilog.rendered_message" && (string?)kvp.Value == "Hello \"World\""); + } + + Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp); + Assert.Equal(DateTimeKind.Utc, logRecord.Timestamp.Kind); + Assert.Equal(LogRecordSeverity.Information, logRecord.Severity); + Assert.Null(logRecord.CategoryName); + + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "greeting" && (string?)kvp.Value == "World"); + + Assert.Equal(default, logRecord.TraceId); + Assert.Equal(default, logRecord.SpanId); + Assert.Null(logRecord.TraceState); + Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags); + } + + [Fact] + public void SerilogBasicLogWithActivityTest() + { + using var activity = new Activity("Test"); + activity.Start(); + + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(loggerProvider, disposeProvider: true) + .CreateLogger(); + + Log.Logger.Information("Hello {greeting}", "World"); + + Log.CloseAndFlush(); + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotEqual(default, logRecord.TraceId); + + Assert.Equal(activity.TraceId, logRecord.TraceId); + Assert.Equal(activity.SpanId, logRecord.SpanId); + Assert.Equal(activity.TraceStateString, logRecord.TraceState); + Assert.Equal(activity.ActivityTraceFlags, logRecord.TraceFlags); + } + + [Fact] + public void SerilogCategoryNameTest() + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(loggerProvider, disposeProvider: true) + .CreateLogger(); + + // Note: Serilog ForContext API is used to set "CategoryName" on log messages + ILogger logger = Log.Logger.ForContext(); + + logger.Information("Hello {greeting}", "World"); + + Log.CloseAndFlush(); + + Assert.Single(exportedItems); + + LogRecord logRecord = exportedItems[0]; + + Assert.Null(logRecord.CategoryName); + + Assert.NotNull(logRecord.Attributes); + + Assert.Contains( + logRecord.Attributes, + kvp => kvp.Key == "serilog.source_context" + && (string?)kvp.Value == "OpenTelemetry.Extensions.Serilog.Tests.OpenTelemetrySerilogSinkTests"); + } + + [Fact] + public void SerilogComplexMessageTemplateTest() + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(loggerProvider, disposeProvider: true) + .CreateLogger(); + + ComplexType complexType = new(); + + Log.Logger.Information("Hello {greeting} {id} {@complexObj} {$complexStr}", "World", 18, complexType, complexType); + + Log.CloseAndFlush(); + + Assert.Single(exportedItems); + + LogRecord logRecord = exportedItems[0]; + + Assert.NotNull(logRecord.Attributes); + Assert.Equal(3, logRecord.Attributes!.Count); // Note: complexObj is currently not supported/ignored. + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "greeting" && (string?)kvp.Value == "World"); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "id" && (int?)kvp.Value == 18); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "complexStr" && (string?)kvp.Value == "ComplexTypeToString"); + } + + [Fact] + public void SerilogArrayMessageTemplateTest() + { + List exportedItems = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(loggerProvider, disposeProvider: true) + .CreateLogger(); + + ComplexType complexType = new(); + + var intArray = new int[] { 0, 1, 2, 3, 4 }; + var mixedArray = new object?[] { 0, null, "3", 18.0D }; + + Log.Logger.Information("Int array {data}", intArray); + Log.Logger.Information("Mixed array {data}", new object[] { mixedArray }); + + Log.CloseAndFlush(); + + Assert.Equal(2, exportedItems.Count); + + LogRecord logRecord = exportedItems[0]; + + Assert.NotNull(logRecord.Attributes); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "data" && kvp.Value is int[] typedArray && intArray.SequenceEqual(typedArray)); + + logRecord = exportedItems[1]; + Assert.NotNull(logRecord.Attributes); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "data" && kvp.Value is object?[] typedArray && mixedArray.SequenceEqual(typedArray)); + } + + [Fact] + public void SerilogExceptionTest() + { + List exportedItems = new(); + + InvalidOperationException ex = new(); + +#pragma warning disable CA2000 // Dispose objects before losing scope + var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); +#pragma warning restore CA2000 // Dispose objects before losing scope + + Log.Logger = new LoggerConfiguration() + .WriteTo.OpenTelemetry(loggerProvider, disposeProvider: true) + .CreateLogger(); + + Log.Logger.Information(ex, "Exception"); + + Log.CloseAndFlush(); + + Assert.Single(exportedItems); + + LogRecord logRecord = exportedItems[0]; + + Assert.Null(logRecord.Exception); + + Assert.NotNull(logRecord.Attributes); + + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == SemanticConventions.AttributeExceptionType && (string?)kvp.Value == ex.GetType().Name); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == SemanticConventions.AttributeExceptionMessage && (string?)kvp.Value == ex.Message); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == SemanticConventions.AttributeExceptionStacktrace && (string?)kvp.Value == ex.ToInvariantString()); + } + + private sealed class DisposeTrackingProcessor : BaseProcessor + { + public bool Disposed { get; private set; } + + protected override void Dispose(bool disposing) + { + this.Disposed = true; + + base.Dispose(disposing); + } + } + + private sealed class ComplexType + { + public override string ToString() => "ComplexTypeToString"; + } + } +} diff --git a/test/OpenTelemetry.Tests.Stress.Logs/Program.cs b/test/OpenTelemetry.Tests.Stress.Logs/Program.cs index 1239e08432c..cc66d13bc06 100644 --- a/test/OpenTelemetry.Tests.Stress.Logs/Program.cs +++ b/test/OpenTelemetry.Tests.Stress.Logs/Program.cs @@ -29,10 +29,7 @@ public static void Main() { using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddOpenTelemetry(options => - { - options.AddProcessor(new DummyProcessor()); - }); + builder.AddOpenTelemetry().AddProcessor(new DummyProcessor()); }); logger = loggerFactory.CreateLogger(); diff --git a/test/OpenTelemetry.Tests/Logs/BatchLogRecordExportProcessorTests.cs b/test/OpenTelemetry.Tests/Logs/BatchLogRecordExportProcessorTests.cs index feb5834ab19..95295f1b482 100644 --- a/test/OpenTelemetry.Tests/Logs/BatchLogRecordExportProcessorTests.cs +++ b/test/OpenTelemetry.Tests/Logs/BatchLogRecordExportProcessorTests.cs @@ -14,7 +14,6 @@ // limitations under the License. // -#if !NETFRAMEWORK using System; using System.Collections.Generic; using Microsoft.Extensions.Logging; @@ -110,4 +109,3 @@ public void StateBufferingTest() } } } -#endif diff --git a/test/OpenTelemetry.Tests/Logs/LogEmitterTests.cs b/test/OpenTelemetry.Tests/Logs/LogEmitterTests.cs new file mode 100644 index 00000000000..c724b9acee8 --- /dev/null +++ b/test/OpenTelemetry.Tests/Logs/LogEmitterTests.cs @@ -0,0 +1,169 @@ +// +// 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 Microsoft.Extensions.Logging; +using Xunit; + +namespace OpenTelemetry.Logs.Tests +{ + public sealed class LogEmitterTests + { + [Fact] + public void LogEmitterBasicTest() + { + var exportedItems = new List(); + + using var provider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); + + var logger = provider.GetLogger("test"); + + logger.EmitLog( + new() + { + Body = "Hello world", + Severity = LogRecordSeverity.Warning, + }, + new() + { + ["key1"] = "value1", + ["key2"] = "value2", + }); + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotNull(logRecord); + Assert.Null(logRecord.CategoryName); + Assert.Null(logRecord.FormattedMessage); + Assert.Equal("Hello world", logRecord.Body); + Assert.Equal(LogLevel.Warning, logRecord.LogLevel); + Assert.Equal(LogRecordSeverity.Warning, logRecord.Severity); + Assert.Equal(default, logRecord.EventId); + Assert.Null(logRecord.Exception); + Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp); + + Assert.Equal(default, logRecord.TraceId); + Assert.Equal(default, logRecord.SpanId); + Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags); + Assert.Null(logRecord.TraceState); + + Assert.NotNull(logRecord.Attributes); + Assert.Equal(2, logRecord.Attributes.Count); + Assert.Contains(logRecord.Attributes, item => item.Key == "key1" && (string)item.Value == "value1"); + Assert.Contains(logRecord.Attributes, item => item.Key == "key2" && (string)item.Value == "value2"); + } + + [Fact] + public void LogEmitterFromActivityTest() + { + var exportedItems = new List(); + + using var provider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); + + var logger = provider.GetLogger(); + + using var activity = new Activity("Test"); + + activity.Start(); + + activity.ActivityTraceFlags = ActivityTraceFlags.Recorded; + activity.TraceStateString = "key1=value1"; + + logger.EmitLog(new(activity)); + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotNull(logRecord); + + Assert.Equal(activity.TraceId, logRecord.TraceId); + Assert.Equal(activity.SpanId, logRecord.SpanId); + Assert.Equal(activity.ActivityTraceFlags, logRecord.TraceFlags); + Assert.Null(logRecord.TraceState); + + Assert.Null(logRecord.Attributes); + } + + [Fact] + public void LogEmitterLocalToUtcTimestampTest() + { + var exportedItems = new List(); + + using var provider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); + + var logger = provider.GetLogger(); + + DateTime timestamp = DateTime.SpecifyKind( + new DateTime(2022, 6, 30, 16, 0, 0), + DateTimeKind.Local); + + logger.EmitLog(new() + { + Timestamp = timestamp, + }); + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotNull(logRecord); + + Assert.Equal(timestamp.ToUniversalTime(), logRecord.Timestamp); + Assert.Equal(DateTimeKind.Utc, logRecord.Timestamp.Kind); + } + + [Fact] + public void LogEmitterUnspecifiedTimestampTest() + { + var exportedItems = new List(); + + using var provider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); + + var logger = provider.GetLogger(new InstrumentationScope()); + + DateTime timestamp = DateTime.SpecifyKind( + new DateTime(2022, 6, 30, 16, 0, 0), + DateTimeKind.Unspecified); + + logger.EmitLog(new() + { + Timestamp = timestamp, + }); + + Assert.Single(exportedItems); + + var logRecord = exportedItems[0]; + + Assert.NotNull(logRecord); + + Assert.Equal(timestamp, logRecord.Timestamp); + Assert.Equal(DateTimeKind.Unspecified, logRecord.Timestamp.Kind); + } + } +} diff --git a/test/OpenTelemetry.Tests/Logs/LogRecordAttributeListTests.cs b/test/OpenTelemetry.Tests/Logs/LogRecordAttributeListTests.cs index d0e068c46b1..7d620a6e0cb 100644 --- a/test/OpenTelemetry.Tests/Logs/LogRecordAttributeListTests.cs +++ b/test/OpenTelemetry.Tests/Logs/LogRecordAttributeListTests.cs @@ -54,7 +54,7 @@ public void ReadWriteTest(int numberOfItems) index++; } - if (attributes.Count <= LogRecordAttributeList.OverflowAdditionalCapacity) + if (attributes.Count <= LogRecordAttributeList.OverflowMaxCount) { Assert.Null(attributes.OverflowAttributes); } @@ -79,20 +79,20 @@ public void ApplyToLogRecordTest(int numberOfItems) attributes.Add($"key{i}", i); } - LogRecord logRecord = new(); + List> storage = null; - attributes.ApplyToLogRecord(logRecord); + var exportedAttributes = attributes.Export(ref storage, additionalCapacity: 0); if (numberOfItems == 0) { - Assert.Null(logRecord.StateValues); + Assert.Null(exportedAttributes); return; } - Assert.NotNull(logRecord.StateValues); + Assert.NotNull(exportedAttributes); int index = 0; - foreach (KeyValuePair item in logRecord.StateValues) + foreach (KeyValuePair item in exportedAttributes) { Assert.Equal($"key{index}", item.Key); Assert.Equal(index, (int)item.Value); diff --git a/test/OpenTelemetry.Tests/Logs/LogRecordTest.cs b/test/OpenTelemetry.Tests/Logs/LogRecordTest.cs index 79fb0d2fa19..65a65745099 100644 --- a/test/OpenTelemetry.Tests/Logs/LogRecordTest.cs +++ b/test/OpenTelemetry.Tests/Logs/LogRecordTest.cs @@ -14,7 +14,6 @@ // limitations under the License. // -#if !NETFRAMEWORK using System; using System.Collections; using System.Collections.Generic; @@ -79,12 +78,18 @@ public void CheckStateForUnstructuredLog() const string message = "Hello, World!"; logger.LogInformation(message); - var state = exportedItems[0].State as IReadOnlyList>; + + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); // state only has {OriginalFormat} - Assert.Equal(1, state.Count); + Assert.Equal(1, attributes.Count); - Assert.Equal(message, state.ToString()); + Assert.Equal(message, exportedItems[0].Body); + Assert.Null(exportedItems[0].FormattedMessage); } [Fact] @@ -96,40 +101,62 @@ public void CheckStateForUnstructuredLogWithStringInterpolation() var message = $"Hello from potato {0.99}."; logger.LogInformation(message); - var state = exportedItems[0].State as IReadOnlyList>; + + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); // state only has {OriginalFormat} - Assert.Equal(1, state.Count); + Assert.Equal(1, attributes.Count); - Assert.Equal(message, state.ToString()); + Assert.Equal(message, exportedItems[0].Body); + Assert.Null(exportedItems[0].FormattedMessage); } - [Fact] - public void CheckStateForStructuredLogWithTemplate() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CheckStateForStructuredLogWithTemplate(bool includeFormattedMessage) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: null); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: o => o.IncludeFormattedMessage = includeFormattedMessage); var logger = loggerFactory.CreateLogger(); const string message = "Hello from {name} {price}."; logger.LogInformation(message, "tomato", 2.99); - var state = exportedItems[0].State as IReadOnlyList>; + + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); // state has name, price and {OriginalFormat} - Assert.Equal(3, state.Count); + Assert.Equal(3, attributes.Count); // Check if state has name - Assert.Contains(state, item => item.Key == "name"); - Assert.Equal("tomato", state.First(item => item.Key == "name").Value); + Assert.Contains(attributes, item => item.Key == "name"); + Assert.Equal("tomato", attributes.First(item => item.Key == "name").Value); // Check if state has price - Assert.Contains(state, item => item.Key == "price"); - Assert.Equal(2.99, state.First(item => item.Key == "price").Value); + Assert.Contains(attributes, item => item.Key == "price"); + Assert.Equal(2.99, attributes.First(item => item.Key == "price").Value); // Check if state has OriginalFormat - Assert.Contains(state, item => item.Key == "{OriginalFormat}"); - Assert.Equal(message, state.First(item => item.Key == "{OriginalFormat}").Value); + Assert.Contains(attributes, item => item.Key == "{OriginalFormat}"); + Assert.Equal(message, attributes.First(item => item.Key == "{OriginalFormat}").Value); - Assert.Equal($"Hello from tomato 2.99.", state.ToString()); + Assert.Equal(message, exportedItems[0].Body); + + if (includeFormattedMessage) + { + Assert.Equal($"Hello from tomato 2.99.", exportedItems[0].FormattedMessage); + } + else + { + Assert.Null(exportedItems[0].FormattedMessage); + } } [Fact] @@ -140,23 +167,28 @@ public void CheckStateForStructuredLogWithStrongType() var food = new Food { Name = "artichoke", Price = 3.99 }; logger.LogInformation("{food}", food); - var state = exportedItems[0].State as IReadOnlyList>; + + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); // state has food and {OriginalFormat} - Assert.Equal(2, state.Count); + Assert.Equal(2, attributes.Count); // Check if state has food - Assert.Contains(state, item => item.Key == "food"); + Assert.Contains(attributes, item => item.Key == "food"); - var foodParameter = (Food)state.First(item => item.Key == "food").Value; + var foodParameter = (Food)attributes.First(item => item.Key == "food").Value; Assert.Equal(food.Name, foodParameter.Name); Assert.Equal(food.Price, foodParameter.Price); // Check if state has OriginalFormat - Assert.Contains(state, item => item.Key == "{OriginalFormat}"); - Assert.Equal("{food}", state.First(item => item.Key == "{OriginalFormat}").Value); + Assert.Contains(attributes, item => item.Key == "{OriginalFormat}"); + Assert.Equal("{food}", attributes.First(item => item.Key == "{OriginalFormat}").Value); - Assert.Equal(food.ToString(), state.ToString()); + Assert.Equal("{food}", exportedItems[0].Body); } [Fact] @@ -167,29 +199,34 @@ public void CheckStateForStructuredLogWithAnonymousType() var anonymousType = new { Name = "pumpkin", Price = 5.99 }; logger.LogInformation("{food}", anonymousType); - var state = exportedItems[0].State as IReadOnlyList>; + + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); // state has food and {OriginalFormat} - Assert.Equal(2, state.Count); + Assert.Equal(2, attributes.Count); // Check if state has food - Assert.Contains(state, item => item.Key == "food"); + Assert.Contains(attributes, item => item.Key == "food"); - var foodParameter = state.First(item => item.Key == "food").Value as dynamic; + var foodParameter = attributes.First(item => item.Key == "food").Value as dynamic; Assert.Equal(anonymousType.Name, foodParameter.Name); Assert.Equal(anonymousType.Price, foodParameter.Price); // Check if state has OriginalFormat - Assert.Contains(state, item => item.Key == "{OriginalFormat}"); - Assert.Equal("{food}", state.First(item => item.Key == "{OriginalFormat}").Value); + Assert.Contains(attributes, item => item.Key == "{OriginalFormat}"); + Assert.Equal("{food}", attributes.First(item => item.Key == "{OriginalFormat}").Value); - Assert.Equal(anonymousType.ToString(), state.ToString()); + Assert.Equal("{food}", exportedItems[0].Body); } [Fact] public void CheckStateForStructuredLogWithGeneralType() { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: null); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: o => o.IncludeFormattedMessage = true); var logger = loggerFactory.CreateLogger(); var food = new Dictionary @@ -198,26 +235,33 @@ public void CheckStateForStructuredLogWithGeneralType() ["Price"] = 299.99, }; logger.LogInformation("{food}", food); - var state = exportedItems[0].State as IReadOnlyList>; + + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); // state only has food and {OriginalFormat} - Assert.Equal(2, state.Count); + Assert.Equal(2, attributes.Count); // Check if state has food - Assert.Contains(state, item => item.Key == "food"); + Assert.Contains(attributes, item => item.Key == "food"); - var foodParameter = state.First(item => item.Key == "food").Value as Dictionary; + var foodParameter = attributes.First(item => item.Key == "food").Value as Dictionary; Assert.True(food.Count == foodParameter.Count && !food.Except(foodParameter).Any()); // Check if state has OriginalFormat - Assert.Contains(state, item => item.Key == "{OriginalFormat}"); - Assert.Equal("{food}", state.First(item => item.Key == "{OriginalFormat}").Value); + Assert.Contains(attributes, item => item.Key == "{OriginalFormat}"); + Assert.Equal("{food}", attributes.First(item => item.Key == "{OriginalFormat}").Value); + + Assert.Equal("{food}", exportedItems[0].Body); var prevCulture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; try { - Assert.Equal("[Name, truffle], [Price, 299.99]", state.ToString()); + Assert.Equal("[Name, truffle], [Price, 299.99]", exportedItems[0].FormattedMessage); } finally { @@ -237,8 +281,13 @@ public void CheckStateForExceptionLogged() const string message = "Exception Occurred"; logger.LogInformation(exception, message); - var state = exportedItems[0].State; - var itemCount = state.GetType().GetProperty("Count").GetValue(state); + Assert.Null(exportedItems[0].State); + + var attributes = exportedItems[0].Attributes; + + Assert.NotNull(attributes); + + var itemCount = attributes.Count; // state only has {OriginalFormat} Assert.Equal(1, itemCount); @@ -247,7 +296,12 @@ public void CheckStateForExceptionLogged() Assert.NotNull(loggedException); Assert.Equal(exceptionMessage, loggedException.Message); - Assert.Equal(message, state.ToString()); + Assert.Null(exportedItems[0].FormattedMessage); + + Assert.Equal(message, exportedItems[0].Body); + + Assert.Equal("{OriginalFormat}", attributes[0].Key); + Assert.Equal(message, attributes[0].Value); } [Fact] @@ -285,14 +339,27 @@ public void CheckStateValuesCanBeSet() Assert.Equal(expectedStateValues, logRecord.StateValues); } - [Fact] - public void CheckFormattedMessageCanBeSet() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CheckFormattedMessageCanBeSet(bool includeFormattedMessage) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.IncludeFormattedMessage = true); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.IncludeFormattedMessage = includeFormattedMessage); var logger = loggerFactory.CreateLogger(); logger.LogInformation("OpenTelemetry {Greeting} {Subject}!", "Hello", "World"); var logRecord = exportedItems[0]; + + Assert.Equal("OpenTelemetry {Greeting} {Subject}!", logRecord.Body); + if (includeFormattedMessage) + { + Assert.Equal("OpenTelemetry Hello World!", logRecord.FormattedMessage); + } + else + { + Assert.Null(logRecord.FormattedMessage); + } + var expectedFormattedMessage = "OpenTelemetry Good Night!"; logRecord.FormattedMessage = expectedFormattedMessage; @@ -408,10 +475,12 @@ public void CheckTraceIdForLogWithinActivityMarkedAsRecordOnly() Assert.Equal(currentActivity.ActivityTraceFlags, logRecord.TraceFlags); } - [Fact] - public void CheckTraceIdForLogWithinActivityMarkedAsRecordAndSample() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CheckTraceIdForLogWithinActivityMarkedAsRecordAndSample(bool includeTraceState) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: null); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: o => o.IncludeTraceState = includeTraceState); var logger = loggerFactory.CreateLogger(); var sampler = new AlwaysOnSampler(); @@ -426,6 +495,10 @@ public void CheckTraceIdForLogWithinActivityMarkedAsRecordAndSample() using var activity = activitySource.StartActivity("Activity"); + Assert.NotNull(activity); + + activity!.TraceStateString = "key1=value1"; + logger.LogInformation("Log within activity marked as RecordAndSample"); var logRecord = exportedItems[0]; @@ -434,32 +507,47 @@ public void CheckTraceIdForLogWithinActivityMarkedAsRecordAndSample() Assert.Equal(currentActivity.TraceId, logRecord.TraceId); Assert.Equal(currentActivity.SpanId, logRecord.SpanId); Assert.Equal(currentActivity.ActivityTraceFlags, logRecord.TraceFlags); + if (includeTraceState) + { + Assert.Equal(currentActivity.TraceStateString, logRecord.TraceState); + } + else + { + Assert.Null(logRecord.TraceState); + } } - [Fact] - public void VerifyIncludeFormattedMessage_False() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void VerifyIncludeFormattedMessage(bool includeFormattedMessage) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.IncludeFormattedMessage = false); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.IncludeFormattedMessage = includeFormattedMessage); var logger = loggerFactory.CreateLogger(); logger.LogInformation("OpenTelemetry!"); var logRecord = exportedItems[0]; - Assert.Null(logRecord.FormattedMessage); - } - - [Fact] - public void VerifyIncludeFormattedMessage_True() - { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.IncludeFormattedMessage = true); - var logger = loggerFactory.CreateLogger(); - logger.LogInformation("OpenTelemetry!"); - var logRecord = exportedItems[0]; - Assert.Equal("OpenTelemetry!", logRecord.FormattedMessage); + if (includeFormattedMessage) + { + Assert.Equal("OpenTelemetry!", logRecord.FormattedMessage); + } + else + { + Assert.Null(logRecord.FormattedMessage); + } logger.LogInformation("OpenTelemetry {Greeting} {Subject}!", "Hello", "World"); logRecord = exportedItems[1]; - Assert.Equal("OpenTelemetry Hello World!", logRecord.FormattedMessage); + + if (includeFormattedMessage) + { + Assert.Equal("OpenTelemetry Hello World!", logRecord.FormattedMessage); + } + else + { + Assert.Null(logRecord.FormattedMessage); + } } [Fact] @@ -596,25 +684,12 @@ public void VerifyIncludeScopes_True() Assert.Same(expectedScope3, scopes[2]); } - [Fact] - public void VerifyParseStateValues_False_UsingStandardExtensions() - { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = false); - var logger = loggerFactory.CreateLogger(); - - // Tests state parsing with standard extensions. - - logger.LogInformation("{Product} {Year}!", "OpenTelemetry", 2021); - var logRecord = exportedItems[0]; - - Assert.NotNull(logRecord.State); - Assert.Null(logRecord.StateValues); - } - - [Fact] - public void VerifyParseStateValues_True_UsingStandardExtensions() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void VerifyParseStateValues_UsingStandardExtensions(bool parseStateValues) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = true); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = parseStateValues); var logger = loggerFactory.CreateLogger(); // Tests state parsing with standard extensions. @@ -629,6 +704,10 @@ public void VerifyParseStateValues_True_UsingStandardExtensions() Assert.Equal(new KeyValuePair("Year", 2021), logRecord.StateValues[1]); Assert.Equal(new KeyValuePair("{OriginalFormat}", "{Product} {Year}!"), logRecord.StateValues[2]); + Assert.NotNull(logRecord.Body); + Assert.Null(logRecord.FormattedMessage); + Assert.Equal("{Product} {Year}!", logRecord.Body); + var complex = new { Property = "Value" }; logger.LogInformation("{Product} {Year} {Complex}!", "OpenTelemetry", 2021, complex); @@ -644,12 +723,18 @@ public void VerifyParseStateValues_True_UsingStandardExtensions() KeyValuePair actualComplex = logRecord.StateValues[2]; Assert.Equal("Complex", actualComplex.Key); Assert.Same(complex, actualComplex.Value); + + Assert.NotNull(logRecord.Body); + Assert.Null(logRecord.FormattedMessage); + Assert.Equal("{Product} {Year} {Complex}!", logRecord.Body); } - [Fact] - public void ParseStateValuesUsingStructTest() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ParseStateValuesUsingStructTest(bool parseStateValues) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = true); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = parseStateValues); var logger = loggerFactory.CreateLogger(); // Tests struct IReadOnlyList> parse path. @@ -666,12 +751,18 @@ public void ParseStateValuesUsingStructTest() Assert.NotNull(logRecord.StateValues); Assert.Equal(1, logRecord.StateValues.Count); Assert.Equal(new KeyValuePair("Key1", "Value1"), logRecord.StateValues[0]); + + Assert.NotNull(logRecord.Body); + Assert.NotNull(logRecord.FormattedMessage); + Assert.Equal("OpenTelemetry!", logRecord.Body); } - [Fact] - public void ParseStateValuesUsingListTest() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ParseStateValuesUsingListTest(bool parseStateValues) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = true); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = parseStateValues); var logger = loggerFactory.CreateLogger(); // Tests ref IReadOnlyList> parse path. @@ -688,12 +779,18 @@ public void ParseStateValuesUsingListTest() Assert.NotNull(logRecord.StateValues); Assert.Equal(1, logRecord.StateValues.Count); Assert.Equal(new KeyValuePair("Key1", "Value1"), logRecord.StateValues[0]); + + Assert.NotNull(logRecord.Body); + Assert.NotNull(logRecord.FormattedMessage); + Assert.Equal("OpenTelemetry!", logRecord.Body); } - [Fact] - public void ParseStateValuesUsingIEnumerableTest() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ParseStateValuesUsingIEnumerableTest(bool parseStateValues) { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = true); + using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = parseStateValues); var logger = loggerFactory.CreateLogger(); // Tests IEnumerable> parse path. @@ -710,19 +807,74 @@ public void ParseStateValuesUsingIEnumerableTest() Assert.NotNull(logRecord.StateValues); Assert.Equal(1, logRecord.StateValues.Count); Assert.Equal(new KeyValuePair("Key1", "Value1"), logRecord.StateValues[0]); + + Assert.NotNull(logRecord.Body); + Assert.NotNull(logRecord.FormattedMessage); + Assert.Equal("OpenTelemetry!", logRecord.Body); } [Fact] - public void ParseStateValuesUsingCustomTest() + public void ParseStateValuesWithOriginalFormatSetsBodyTest() { - using var loggerFactory = InitializeLoggerFactory(out List exportedItems, configure: options => options.ParseStateValues = true); + using var loggerFactory = InitializeLoggerFactory( + out List exportedItems, + configure: options => + { + options.ParseStateValues = false; + options.IncludeFormattedMessage = false; + }); + var logger = loggerFactory.CreateLogger(); + + logger.Log( + LogLevel.Information, + 0, + new ListState(new KeyValuePair("{OriginalFormat}", "Message_Template_Goes_Here")), + null, + (s, e) => "OpenTelemetry!"); + + var logRecord = exportedItems[0]; + + Assert.NotNull(logRecord.Body); + Assert.Equal("Message_Template_Goes_Here", logRecord.Body); + Assert.Null(logRecord.FormattedMessage); + + exportedItems.Clear(); + + logger.Log( + LogLevel.Information, + 0, + new ListState( + new KeyValuePair("{OriginalFormat}", "Message_Template_Goes_Here"), // <- Ignored because it is not the last item + new KeyValuePair("Key1", "Value1")), + null, + (s, e) => "OpenTelemetry!"); + + logRecord = exportedItems[0]; + + Assert.Equal("OpenTelemetry!", logRecord.Body); + Assert.Equal("OpenTelemetry!", logRecord.FormattedMessage); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ParseStateValuesUsingCustomTest(bool parseStateValues) + { + using var loggerFactory = InitializeLoggerFactory( + out List exportedItems, + configure: options => + { + options.ParseStateValues = parseStateValues; + options.IncludeFormattedMessage = false; + }); var logger = loggerFactory.CreateLogger(); // Tests unknown state parse path. CustomState state = new CustomState { - Property = "Value", + Property1 = "Value1", + Property2 = "Value2", }; logger.Log( @@ -731,16 +883,27 @@ public void ParseStateValuesUsingCustomTest() state, null, (s, e) => "OpenTelemetry!"); + var logRecord = exportedItems[0]; - Assert.Null(logRecord.State); - Assert.NotNull(logRecord.StateValues); - Assert.Equal(1, logRecord.StateValues.Count); + if (parseStateValues) + { + Assert.Null(logRecord.State); + Assert.NotNull(logRecord.Attributes); + Assert.Equal(2, logRecord.Attributes.Count); - KeyValuePair actualState = logRecord.StateValues[0]; + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "Property1" && (string)kvp.Value == "Value1"); + Assert.Contains(logRecord.Attributes, kvp => kvp.Key == "Property2" && (string)kvp.Value == "Value2"); + } + else + { + Assert.NotNull(logRecord.State); + Assert.Null(logRecord.Attributes); + } - Assert.Equal(string.Empty, actualState.Key); - Assert.Same(state, actualState.Value); + Assert.NotNull(logRecord.Body); + Assert.NotNull(logRecord.FormattedMessage); + Assert.Equal("OpenTelemetry!", logRecord.Body); } [Fact] @@ -913,8 +1076,13 @@ IEnumerator IEnumerable.GetEnumerator() private class CustomState { - public string Property { get; set; } + public int Field1 = 18; + + public string Property1 { get; set; } + + public string Property2 { get; set; } + + public string Property3 { get; set; } } } } -#endif diff --git a/test/OpenTelemetry.Tests/Logs/LoggerFactoryAndResourceBuilderTests.cs b/test/OpenTelemetry.Tests/Logs/LoggerFactoryAndResourceBuilderTests.cs index d8f6cb404c5..d7b54100560 100644 --- a/test/OpenTelemetry.Tests/Logs/LoggerFactoryAndResourceBuilderTests.cs +++ b/test/OpenTelemetry.Tests/Logs/LoggerFactoryAndResourceBuilderTests.cs @@ -68,7 +68,7 @@ private static void VerifyResourceBuilder( }); var logger = loggerFactory.CreateLogger(); - var provider = exporter.ParentProvider as OpenTelemetryLoggerProvider; + var provider = exporter.ParentProvider as LoggerProviderSdk; Assert.NotNull(provider); var resource = provider.GetResource(); Assert.NotNull(resource); diff --git a/test/OpenTelemetry.Tests/Logs/LoggerOptionsTest.cs b/test/OpenTelemetry.Tests/Logs/LoggerOptionsTest.cs index 57989649553..763ca93c498 100644 --- a/test/OpenTelemetry.Tests/Logs/LoggerOptionsTest.cs +++ b/test/OpenTelemetry.Tests/Logs/LoggerOptionsTest.cs @@ -25,18 +25,22 @@ public sealed class LoggerOptionsTest [InlineData(false)] public void VerifyOptionsCannotBeChangedAfterInit(bool initialValue) { - var options = new OpenTelemetryLoggerOptions + OpenTelemetryLoggerOptions options = new() { IncludeFormattedMessage = initialValue, IncludeScopes = initialValue, ParseStateValues = initialValue, }; - var provider = new OpenTelemetryLoggerProvider(options); + + using var provider = Sdk.CreateLoggerProviderBuilder() + .Build(); + + using var openTelemetryLoggerProvider = new OpenTelemetryLoggerProvider(options, provider, disposeProvider: false); // Verify initial set - Assert.Equal(initialValue, provider.IncludeFormattedMessage); - Assert.Equal(initialValue, provider.IncludeScopes); - Assert.Equal(initialValue, provider.ParseStateValues); + Assert.Equal(initialValue, openTelemetryLoggerProvider.IncludeFormattedMessage); + Assert.Equal(initialValue, openTelemetryLoggerProvider.IncludeScopes); + Assert.Equal(initialValue, openTelemetryLoggerProvider.ParseStateValues); Assert.NotNull(options); @@ -46,9 +50,9 @@ public void VerifyOptionsCannotBeChangedAfterInit(bool initialValue) options.ParseStateValues = !initialValue; // Verify processor is unchanged - Assert.Equal(initialValue, provider.IncludeFormattedMessage); - Assert.Equal(initialValue, provider.IncludeScopes); - Assert.Equal(initialValue, provider.ParseStateValues); + Assert.Equal(initialValue, openTelemetryLoggerProvider.IncludeFormattedMessage); + Assert.Equal(initialValue, openTelemetryLoggerProvider.IncludeScopes); + Assert.Equal(initialValue, openTelemetryLoggerProvider.ParseStateValues); } } } diff --git a/test/OpenTelemetry.Tests/Logs/LoggerProviderBuilderExtensionsTests.cs b/test/OpenTelemetry.Tests/Logs/LoggerProviderBuilderExtensionsTests.cs new file mode 100644 index 00000000000..74a3cc54fc1 --- /dev/null +++ b/test/OpenTelemetry.Tests/Logs/LoggerProviderBuilderExtensionsTests.cs @@ -0,0 +1,190 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace OpenTelemetry.Logs.Tests; + +public sealed class LoggerProviderBuilderExtensionsTests +{ + [Fact] + public void LoggerProviderBuilderAddExporterTest() + { + var builder = Sdk.CreateLoggerProviderBuilder(); + + builder.AddExporter(ExportProcessorType.Simple, new CustomExporter()); + builder.AddExporter(ExportProcessorType.Batch); + + using var provider = builder.Build() as LoggerProviderSdk; + + Assert.NotNull(provider); + + var processor = provider.Processor as CompositeProcessor; + + Assert.NotNull(processor); + + var firstProcessor = processor!.Head.Value; + var secondProcessor = processor.Head.Next?.Value; + + Assert.True(firstProcessor is SimpleLogRecordExportProcessor simpleProcessor && simpleProcessor.Exporter is CustomExporter); + Assert.True(secondProcessor is BatchLogRecordExportProcessor batchProcessor && batchProcessor.Exporter is CustomExporter); + } + + [Fact] + public void LoggerProviderBuilderAddExporterWithOptionsTest() + { + int optionsInvocations = 0; + + var builder = Sdk.CreateLoggerProviderBuilder(); + + builder.ConfigureServices(services => + { + services.Configure(options => + { + // Note: This is testing options integration + + optionsInvocations++; + + options.BatchExportProcessorOptions.MaxExportBatchSize = 18; + }); + }); + + builder.AddExporter( + ExportProcessorType.Simple, + new CustomExporter(), + options => + { + // Note: Options delegate isn't invoked for simple processor type + Assert.True(false); + }); + builder.AddExporter( + ExportProcessorType.Batch, + options => + { + optionsInvocations++; + + Assert.Equal(18, options.BatchExportProcessorOptions.MaxExportBatchSize); + + options.BatchExportProcessorOptions.MaxExportBatchSize = 100; + }); + + using var provider = builder.Build() as LoggerProviderSdk; + + Assert.NotNull(provider); + + Assert.Equal(2, optionsInvocations); + + var processor = provider.Processor as CompositeProcessor; + + Assert.NotNull(processor); + + var firstProcessor = processor!.Head.Value; + var secondProcessor = processor.Head.Next?.Value; + + Assert.True(firstProcessor is SimpleLogRecordExportProcessor simpleProcessor && simpleProcessor.Exporter is CustomExporter); + Assert.True(secondProcessor is BatchLogRecordExportProcessor batchProcessor + && batchProcessor.Exporter is CustomExporter + && batchProcessor.MaxExportBatchSize == 100); + } + + [Fact] + public void LoggerProviderBuilderAddExporterNamedOptionsTest() + { + var builder = Sdk.CreateLoggerProviderBuilder(); + + int defaultOptionsConfigureInvocations = 0; + int namedOptionsConfigureInvocations = 0; + + builder.ConfigureServices(services => + { + services.Configure(o => defaultOptionsConfigureInvocations++); + + services.Configure("Exporter2", o => namedOptionsConfigureInvocations++); + }); + + builder.AddExporter(ExportProcessorType.Batch, new CustomExporter()); + builder.AddExporter(ExportProcessorType.Batch, new CustomExporter(), name: "Exporter2", configure: null); + builder.AddExporter(ExportProcessorType.Batch); + builder.AddExporter(ExportProcessorType.Batch, name: "Exporter2", configure: null); + + using var provider = builder.Build(); + + Assert.NotNull(provider); + + Assert.Equal(1, defaultOptionsConfigureInvocations); + Assert.Equal(1, namedOptionsConfigureInvocations); + } + + [Fact] + public void LoggerProviderBuilderAddInstrumentationTest() + { + List? instrumentation = null; + + using (var provider = Sdk.CreateLoggerProviderBuilder() + .AddInstrumentation() + .AddInstrumentation((sp, provider) => new CustomInstrumentation(provider)) + .Build() as LoggerProviderSdk) + { + Assert.NotNull(provider); + + Assert.Equal(2, provider.Instrumentations.Count); + + Assert.Null(((CustomInstrumentation)provider.Instrumentations[0]).Provider); + Assert.False(((CustomInstrumentation)provider.Instrumentations[0]).Disposed); + + Assert.NotNull(((CustomInstrumentation)provider.Instrumentations[1]).Provider); + Assert.False(((CustomInstrumentation)provider.Instrumentations[1]).Disposed); + + instrumentation = new List(provider.Instrumentations); + } + + Assert.True(((CustomInstrumentation)instrumentation[0]).Disposed); + Assert.True(((CustomInstrumentation)instrumentation[1]).Disposed); + } + + private sealed class CustomInstrumentation : IDisposable + { + public bool Disposed; + public LoggerProvider? Provider; + + public CustomInstrumentation() + { + } + + public CustomInstrumentation(LoggerProvider provider) + { + this.Provider = provider; + } + + public void Dispose() + { + this.Disposed = true; + } + } + + private sealed class CustomExporter : BaseExporter + { + public override ExportResult Export(in Batch batch) + { + return ExportResult.Success; + } + } +} diff --git a/test/OpenTelemetry.Tests/Logs/LoggerProviderSdkTests.cs b/test/OpenTelemetry.Tests/Logs/LoggerProviderSdkTests.cs new file mode 100644 index 00000000000..ac50fef9dcf --- /dev/null +++ b/test/OpenTelemetry.Tests/Logs/LoggerProviderSdkTests.cs @@ -0,0 +1,122 @@ +// +// 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; +using OpenTelemetry.Exporter; +using OpenTelemetry.Resources; +using Xunit; + +namespace OpenTelemetry.Logs.Tests +{ + public sealed class LoggerProviderSdkTests + { + [Fact] + public void ConfigureCtorTests() + { + using var provider = Sdk.CreateLoggerProviderBuilder() + .SetResourceBuilder(ResourceBuilder + .CreateEmpty() + .AddAttributes(new[] { new KeyValuePair("key1", "value1") })) + .AddInMemoryExporter(new List()) + .Build() as LoggerProviderSdk; + + Assert.NotNull(provider); + + Assert.NotNull(provider.Processor); + Assert.NotNull(provider.Resource); + Assert.Contains(provider.Resource.Attributes, value => value.Key == "key1" && (string)value.Value == "value1"); + } + + [Fact] + public void ForceFlushTest() + { + using var provider = Sdk.CreateLoggerProviderBuilder().Build() as LoggerProviderSdk; + + Assert.True(provider.ForceFlush()); + + List exportedItems = new(); + + provider.AddProcessor(new BatchLogRecordExportProcessor(new InMemoryExporter(exportedItems))); + + var logger = provider.GetLogger("TestLogger"); + + logger.EmitLog(new() { Body = "Hello world" }); + + Assert.Empty(exportedItems); + + Assert.True(provider.ForceFlush()); + + Assert.Single(exportedItems); + } + + [Fact] + public void ThreadStaticPoolUsedByProviderTests() + { + using var provider1 = Sdk.CreateLoggerProviderBuilder().Build() as LoggerProviderSdk; + + Assert.Equal(LogRecordThreadStaticPool.Instance, provider1.LogRecordPool); + + using var provider2 = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())) + .Build() as LoggerProviderSdk; + + Assert.Equal(LogRecordThreadStaticPool.Instance, provider2.LogRecordPool); + + using var provider3 = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())) + .AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())) + .Build() as LoggerProviderSdk; + + Assert.Equal(LogRecordThreadStaticPool.Instance, provider3.LogRecordPool); + } + + [Fact] + public void SharedPoolUsedByProviderTests() + { + using var provider1 = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter())) + .Build() as LoggerProviderSdk; + + Assert.Equal(LogRecordSharedPool.Current, provider1.LogRecordPool); + + using var provider2 = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())) + .AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter())) + .Build() as LoggerProviderSdk; + + Assert.Equal(LogRecordSharedPool.Current, provider2.LogRecordPool); + + using var provider3 = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())) + .AddProcessor(new CompositeProcessor(new BaseProcessor[] + { + new SimpleLogRecordExportProcessor(new NoopExporter()), + new BatchLogRecordExportProcessor(new NoopExporter()), + })) + .Build() as LoggerProviderSdk; + + Assert.Equal(LogRecordSharedPool.Current, provider3.LogRecordPool); + } + + private sealed class NoopExporter : BaseExporter + { + public override ExportResult Export(in Batch batch) + { + return ExportResult.Success; + } + } + } +} diff --git a/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerOptionsSdkTests.cs b/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerOptionsSdkTests.cs new file mode 100644 index 00000000000..e536038d5a4 --- /dev/null +++ b/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerOptionsSdkTests.cs @@ -0,0 +1,112 @@ +// +// 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. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using OpenTelemetry.Resources; +using Xunit; + +namespace OpenTelemetry.Logs.Tests; + +public class OpenTelemetryLoggerOptionsSdkTests +{ + [Fact] + public void CreateLoggerProviderBuilderBuildValidProviderTest() + { + List exportedItems = new(); + + using var provider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); + + Assert.NotNull(provider); + + provider.GetLogger().EmitLog(new() + { + Body = "Hello world", + }); + + Assert.Single(exportedItems); + } + + [Fact] + public void CreateLoggerProviderBuilderExtensionPointsTest() + { + int configureBuilderInvocations = 0; + + var returnedBuilder = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new CustomProcessor()) + .AddProcessor() + .ConfigureServices(services => + { + services.AddSingleton(); + }) + .ConfigureBuilder((sp, o) => + { + configureBuilderInvocations++; + + Assert.Throws(() => o.ConfigureServices(s => { })); + + o.ConfigureResource(r => r.AddAttributes(new Dictionary { ["key1"] = "value1" })); + + o.ConfigureBuilder((sp, b) => configureBuilderInvocations++); + }) + .ConfigureBuilder((sp, p) => + { + Assert.NotNull(sp); + + Assert.NotNull(sp.GetService()); + }); + + using var provider = returnedBuilder.Build() as LoggerProviderSdk; + + Assert.NotNull(provider); + + Assert.Throws(() => returnedBuilder.ConfigureServices(s => { })); + Assert.Throws(() => returnedBuilder.ConfigureResource(r => { })); + Assert.Throws(() => returnedBuilder.ConfigureBuilder((sp, p) => { })); + Assert.Throws(() => returnedBuilder.Build()); + + Assert.Equal(2, configureBuilderInvocations); + + Assert.NotNull(provider.Resource?.Attributes); + Assert.Contains(provider.Resource!.Attributes, kvp => kvp.Key == "key1" && (string)kvp.Value == "value1"); + + var processor = provider.Processor as CompositeProcessor; + Assert.NotNull(processor); + + int count = 0; + var current = processor?.Head; + while (current != null) + { + count++; + current = current.Next; + } + + Assert.Equal(2, count); + } + + private sealed class TestClass1 + { + } + + private sealed class CustomProcessor : BaseProcessor + { + } +} diff --git a/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerProviderTests.cs b/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerProviderTests.cs index 6ddd5d7caa4..cc5f2f37471 100644 --- a/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerProviderTests.cs +++ b/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggerProviderTests.cs @@ -14,9 +14,9 @@ // limitations under the License. // +using System; using System.Collections.Generic; -using Microsoft.Extensions.Logging; -using OpenTelemetry.Exporter; +using Microsoft.Extensions.Options; using OpenTelemetry.Resources; using Xunit; @@ -25,124 +25,79 @@ namespace OpenTelemetry.Logs.Tests public sealed class OpenTelemetryLoggerProviderTests { [Fact] - public void DefaultCtorTests() + public void OptionsCtorTests() { OpenTelemetryLoggerOptions defaults = new(); - using OpenTelemetryLoggerProvider provider = new(); + using OpenTelemetryLoggerProvider openTelemetryLoggerProvider = new(new TestOptions(new())); + + Assert.Equal(defaults.IncludeState, openTelemetryLoggerProvider.IncludeState); + Assert.Equal(defaults.IncludeTraceState, openTelemetryLoggerProvider.IncludeTraceState); + Assert.Equal(defaults.IncludeScopes, openTelemetryLoggerProvider.IncludeScopes); + Assert.Equal(defaults.IncludeFormattedMessage, openTelemetryLoggerProvider.IncludeFormattedMessage); + Assert.Equal(defaults.ParseStateValues, openTelemetryLoggerProvider.ParseStateValues); + + var provider = openTelemetryLoggerProvider.Provider as LoggerProviderSdk; + + Assert.NotNull(provider); - Assert.Equal(defaults.IncludeScopes, provider.IncludeScopes); - Assert.Equal(defaults.IncludeFormattedMessage, provider.IncludeFormattedMessage); - Assert.Equal(defaults.ParseStateValues, provider.ParseStateValues); Assert.Null(provider.Processor); Assert.NotNull(provider.Resource); } [Fact] - public void ConfigureCtorTests() + public void OptionsCtorWithConfigurationTest() { OpenTelemetryLoggerOptions defaults = new(); - using OpenTelemetryLoggerProvider provider = new(options => + var options = new OpenTelemetryLoggerOptions { - options.IncludeScopes = !defaults.IncludeScopes; - options.IncludeFormattedMessage = !defaults.IncludeFormattedMessage; - options.ParseStateValues = !defaults.ParseStateValues; - - options.SetResourceBuilder(ResourceBuilder + IncludeState = !defaults.IncludeState, + IncludeTraceState = !defaults.IncludeTraceState, + IncludeScopes = !defaults.IncludeScopes, + IncludeFormattedMessage = !defaults.IncludeFormattedMessage, + ParseStateValues = !defaults.ParseStateValues, + }; + + options + .SetResourceBuilder(ResourceBuilder .CreateEmpty() - .AddAttributes(new[] { new KeyValuePair("key1", "value1") })); - - options.AddInMemoryExporter(new List()); - }); - - Assert.Equal(!defaults.IncludeScopes, provider.IncludeScopes); - Assert.Equal(!defaults.IncludeFormattedMessage, provider.IncludeFormattedMessage); - Assert.Equal(!defaults.ParseStateValues, provider.ParseStateValues); - Assert.NotNull(provider.Processor); - Assert.NotNull(provider.Resource); - Assert.Contains(provider.Resource.Attributes, value => value.Key == "key1" && (string)value.Value == "value1"); - } + .AddAttributes(new[] { new KeyValuePair("key1", "value1") })) + .AddInMemoryExporter(new List()); - [Fact] - public void ForceFlushTest() - { - using OpenTelemetryLoggerProvider provider = new(); - - Assert.True(provider.ForceFlush()); - - List exportedItems = new(); - - provider.AddProcessor(new BatchLogRecordExportProcessor(new InMemoryExporter(exportedItems))); + using OpenTelemetryLoggerProvider openTelemetryLoggerProvider = new(new TestOptions(options)); - var logger = provider.CreateLogger("TestLogger"); + Assert.Equal(!defaults.IncludeState, openTelemetryLoggerProvider.IncludeState); + Assert.Equal(!defaults.IncludeTraceState, openTelemetryLoggerProvider.IncludeTraceState); + Assert.Equal(!defaults.IncludeScopes, openTelemetryLoggerProvider.IncludeScopes); + Assert.Equal(!defaults.IncludeFormattedMessage, openTelemetryLoggerProvider.IncludeFormattedMessage); + Assert.Equal(!defaults.ParseStateValues, openTelemetryLoggerProvider.ParseStateValues); - logger.LogInformation("hello world"); + var provider = openTelemetryLoggerProvider.Provider as LoggerProviderSdk; - Assert.Empty(exportedItems); + Assert.NotNull(provider); - Assert.True(provider.ForceFlush()); - - Assert.Single(exportedItems); - } - - [Fact] - public void ThreadStaticPoolUsedByProviderTests() - { - using var provider1 = new OpenTelemetryLoggerProvider(new OpenTelemetryLoggerOptions()); - - Assert.Equal(LogRecordThreadStaticPool.Instance, provider1.LogRecordPool); - - var options = new OpenTelemetryLoggerOptions(); - options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())); - - using var provider2 = new OpenTelemetryLoggerProvider(options); - - Assert.Equal(LogRecordThreadStaticPool.Instance, provider2.LogRecordPool); - - options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())); - - using var provider3 = new OpenTelemetryLoggerProvider(options); - - Assert.Equal(LogRecordThreadStaticPool.Instance, provider3.LogRecordPool); + Assert.NotNull(provider.Processor); + Assert.NotNull(provider.Resource); + Assert.Contains(provider.Resource.Attributes, value => value.Key == "key1" && (string)value.Value == "value1"); } - [Fact] - public void SharedPoolUsedByProviderTests() + private sealed class TestOptions : IOptionsMonitor { - var options = new OpenTelemetryLoggerOptions(); - options.AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter())); - - using var provider1 = new OpenTelemetryLoggerProvider(options); - - Assert.Equal(LogRecordSharedPool.Current, provider1.LogRecordPool); - - options = new OpenTelemetryLoggerOptions(); - options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())); - options.AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter())); - - using var provider2 = new OpenTelemetryLoggerProvider(options); + private readonly OpenTelemetryLoggerOptions options; - Assert.Equal(LogRecordSharedPool.Current, provider2.LogRecordPool); - - options = new OpenTelemetryLoggerOptions(); - options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter())); - options.AddProcessor(new CompositeProcessor(new BaseProcessor[] + public TestOptions(OpenTelemetryLoggerOptions options) { - new SimpleLogRecordExportProcessor(new NoopExporter()), - new BatchLogRecordExportProcessor(new NoopExporter()), - })); + this.options = options; + } - using var provider3 = new OpenTelemetryLoggerProvider(options); + public OpenTelemetryLoggerOptions CurrentValue => this.options; - Assert.Equal(LogRecordSharedPool.Current, provider3.LogRecordPool); - } + public OpenTelemetryLoggerOptions Get(string name) => this.options; - private sealed class NoopExporter : BaseExporter - { - public override ExportResult Export(in Batch batch) + public IDisposable OnChange(Action listener) { - return ExportResult.Success; + throw new NotImplementedException(); } } } diff --git a/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggingExtensionsTests.cs b/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggingExtensionsTests.cs index c6a6aa5a893..1f98fb6ae77 100644 --- a/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggingExtensionsTests.cs +++ b/test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggingExtensionsTests.cs @@ -16,8 +16,11 @@ #nullable enable +using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using OpenTelemetry.Resources; using Xunit; namespace OpenTelemetry.Logs.Tests; @@ -25,7 +28,7 @@ namespace OpenTelemetry.Logs.Tests; public sealed class OpenTelemetryLoggingExtensionsTests { [Fact] - public void ServiceCollectionAddOpenTelemetryNoParametersTest() + public void LoggingBuilderAddOpenTelemetryNoParametersTest() { bool optionsCallbackInvoked = false; @@ -51,10 +54,9 @@ public void ServiceCollectionAddOpenTelemetryNoParametersTest() } [Theory] - [InlineData(1, 0)] - [InlineData(1, 1)] - [InlineData(5, 5)] - public void ServiceCollectionAddOpenTelemetryConfigureActionTests(int numberOfBuilderRegistrations, int numberOfOptionsRegistrations) + [InlineData(1)] + [InlineData(5)] + public void LoggingBuilderAddOpenTelemetryConfigureActionTests(int numberOfOptionsRegistrations) { int configureCallbackInvocations = 0; int optionsCallbackInvocations = 0; @@ -64,10 +66,8 @@ public void ServiceCollectionAddOpenTelemetryConfigureActionTests(int numberOfBu serviceCollection.AddLogging(configure => { - for (int i = 0; i < numberOfBuilderRegistrations; i++) - { - configure.AddOpenTelemetry(ConfigureCallback); - } + configure.AddOpenTelemetry(); // <- Just to verify this doesn't cause a throw. + configure.AddOpenTelemetry(ConfigureCallback); }); for (int i = 0; i < numberOfOptionsRegistrations; i++) @@ -75,15 +75,15 @@ public void ServiceCollectionAddOpenTelemetryConfigureActionTests(int numberOfBu serviceCollection.Configure(OptionsCallback); } + Assert.Null(optionsInstance); + using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); ILoggerFactory? loggerFactory = serviceProvider.GetService(); Assert.NotNull(loggerFactory); - Assert.NotNull(optionsInstance); - - Assert.Equal(numberOfBuilderRegistrations, configureCallbackInvocations); + Assert.Equal(1, configureCallbackInvocations); Assert.Equal(numberOfOptionsRegistrations, optionsCallbackInvocations); void ConfigureCallback(OpenTelemetryLoggerOptions options) @@ -94,7 +94,8 @@ void ConfigureCallback(OpenTelemetryLoggerOptions options) } else { - Assert.Equal(optionsInstance, options); + // Note: In the callback phase each options instance is unique + Assert.NotEqual(optionsInstance, options); } configureCallbackInvocations++; @@ -108,10 +109,382 @@ void OptionsCallback(OpenTelemetryLoggerOptions options) } else { + // Note: In the options phase each instance is the same Assert.Equal(optionsInstance, options); } optionsCallbackInvocations++; } } + + [Fact] + public void LoggingBuilderAddOpenTelemetryMultipleBuildersTest() + { + var serviceCollection = new ServiceCollection(); + + serviceCollection.AddLogging(configure => + { + configure.AddOpenTelemetry().ConfigureResource( + r => r.AddAttributes(new Dictionary() { ["key1"] = "value1" })); + configure.AddOpenTelemetry().ConfigureResource( + r => r.AddAttributes(new Dictionary() { ["key2"] = "value2" })); + }); + + using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); + + var loggerFactory = serviceProvider.GetService(); + + Assert.NotNull(loggerFactory); + + var provider = serviceProvider.GetRequiredService() as LoggerProviderSdk; + + Assert.NotNull(provider); + + Assert.Contains(provider!.Resource.Attributes, kvp => kvp.Key == "key1" && (string)kvp.Value == "value1"); + Assert.Contains(provider!.Resource.Attributes, kvp => kvp.Key == "key2" && (string)kvp.Value == "value2"); + } + + [Fact] + public void LoggingBuilderAddOpenTelemetryWithProviderTest() + { + var provider = new WrappedLoggerProvider(); + + var serviceCollection = new ServiceCollection(); + + serviceCollection.AddLogging(configure => + { + configure.AddOpenTelemetry(provider, configureOptions: null, disposeProvider: true); + }); + + using (ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider()) + { + ILoggerFactory? loggerFactory = serviceProvider.GetService(); + + Assert.NotNull(loggerFactory); + + loggerFactory!.Dispose(); + + // Note: Provider disposal does not actually happen until serviceProvider is disposed + Assert.False(provider.Disposed); + } + + Assert.True(provider.Disposed); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LoggingBuilderAddOpenTelemetryWithProviderAndDisposeSpecifiedTests(bool dispose) + { + var provider = new WrappedLoggerProvider(); + + var serviceCollection = new ServiceCollection(); + + serviceCollection.AddLogging(configure => + { + configure.AddOpenTelemetry(provider, configureOptions: null, disposeProvider: dispose); + }); + + using (ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider()) + { + ILoggerFactory? loggerFactory = serviceProvider.GetService(); + + Assert.NotNull(loggerFactory); + + loggerFactory!.Dispose(); + + // Note: Provider disposal does not actually happen until serviceProvider is disposed + Assert.False(provider.Disposed); + } + + Assert.Equal(dispose, provider.Disposed); + + provider.Dispose(); + + Assert.True(provider.Disposed); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LoggerFactoryCreateAddOpenTelemetryWithProviderAndDisposeSpecifiedTests(bool dispose) + { + var provider = new WrappedLoggerProvider(); + + using (var factory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(provider, configureOptions: null, disposeProvider: dispose); + })) + { + Assert.False(provider.Disposed); + } + + Assert.Equal(dispose, provider.Disposed); + + provider.Dispose(); + + Assert.True(provider.Disposed); + } + + [Fact] + public void LoggingBuilderAddOpenTelemetryProcessorThroughDependencyTest() + { + CustomProcessor.InstanceCount = 0; + + var services = new ServiceCollection(); + + services.AddLogging(builder => + { + builder.AddOpenTelemetry().AddProcessor(); + }); + + CustomProcessor? customProcessor = null; + + using (var serviceProvider = services.BuildServiceProvider()) + { + var loggerFactory = serviceProvider.GetRequiredService(); + + customProcessor = serviceProvider.GetRequiredService(); + + Assert.NotNull(customProcessor); + + loggerFactory.Dispose(); + + Assert.False(customProcessor!.Disposed); + } + + Assert.True(customProcessor.Disposed); + + Assert.Equal(1, CustomProcessor.InstanceCount); + } + + [Fact] + public void LoggingBuilderAddOpenTelemetryConfigureCallbackTest() + { + var services = new ServiceCollection(); + + services.AddSingleton(); + + CustomProcessor? customProcessor = null; + + services.AddLogging(builder => + { + builder.AddOpenTelemetry().ConfigureBuilder((sp, builder) => + { + var testClass = sp.GetRequiredService(); + + customProcessor = new CustomProcessor + { + TestClass = testClass, + }; + + builder.AddProcessor(customProcessor); + }); + }); + + using var serviceProvider = services.BuildServiceProvider(); + + var loggerFactory = serviceProvider.GetRequiredService(); + + Assert.NotNull(customProcessor?.TestClass); + } + + [Fact] + public void LoggingBuilderAddOpenTelemetryOptionsOrderingTest() + { + var services = new ServiceCollection(); + + services.Configure(options => + { + // Note: This will be applied first to the final options + options.IncludeFormattedMessage = true; + options.IncludeScopes = true; + options.ParseStateValues = true; + }); + + services.AddLogging(builder => + { + builder.AddOpenTelemetry(options => + { + // Note: This will be applied second to the final options + options.IncludeFormattedMessage = false; + options.ParseStateValues = false; + }); + }); + + services.Configure(options => + { + // Note: This will be applied last to the final options + options.ParseStateValues = true; + }); + + using var serviceProvider = services.BuildServiceProvider(); + + var loggerFactory = serviceProvider.GetRequiredService(); + + var finalOptions = serviceProvider.GetRequiredService>().CurrentValue; + + Assert.False(finalOptions.IncludeFormattedMessage); + Assert.True(finalOptions.IncludeScopes); + Assert.True(finalOptions.ParseStateValues); + } + + [Fact] + public void LoggingBuilderConfigureOpenTelemetryOrderingTest() + { + int configureInvocationCount = 0; + + var services = new ServiceCollection(); + + LoggerProviderBuilder? builder = null; + + services.ConfigureOpenTelemetryLogging(options => + { + // Note: This will be applied first to the final options + options.AddProcessor(new CustomProcessor(0)); + + options.ConfigureBuilder((sp, b) => + { + Assert.Null(builder); + builder = b; + configureInvocationCount++; + }); + }); + + services.AddLogging(loggingBuilder => + { + var loggerBuilder = loggingBuilder.AddOpenTelemetry(); + + // Note: This be applied second to the final options + + loggerBuilder.AddProcessor(new CustomProcessor(1)); + + loggerBuilder.ConfigureBuilder((sp, b) => + { + configureInvocationCount++; + + Assert.NotNull(builder); + Assert.Equal(builder, b); + }); + }); + + services.ConfigureOpenTelemetryLogging(options => + { + options.AddProcessor(new CustomProcessor(2)); + + options.ConfigureBuilder((sp, b) => + { + configureInvocationCount++; + + Assert.NotNull(builder); + Assert.Equal(builder, b); + }); + }); + + using var serviceProvider = services.BuildServiceProvider(); + + var loggerFactory = serviceProvider.GetRequiredService(); + + Assert.NotNull(builder); + Assert.Equal(3, configureInvocationCount); + + var provider = serviceProvider.GetRequiredService() as LoggerProviderSdk; + + Assert.NotNull(provider); + + var processor = provider!.Processor as CompositeProcessor; + + Assert.NotNull(processor); + + int count = 0; + var current = processor!.Head; + while (current != null) + { + var instance = current.Value as CustomProcessor; + Assert.Equal(count, instance?.Id); + + count++; + current = current.Next; + } + + Assert.Equal(3, count); + } + + [Fact] + public void LoggingBuilderAddOpenTelemetryResourceTest() + { + var services = new ServiceCollection(); + + services.AddLogging(builder => + { + builder.AddOpenTelemetry().SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("Examples.LoggingExtensions")); + }); + + services.ConfigureOpenTelemetryLogging(options => + { + options.ConfigureResource(builder => builder.AddAttributes(new Dictionary { ["key1"] = "value1" })); + }); + + services.ConfigureOpenTelemetryLogging(options => + { + options.ConfigureResource(builder => builder.AddAttributes(new Dictionary { ["key2"] = "value2" })); + }); + + using var serviceProvider = services.BuildServiceProvider(); + + var loggerFactory = serviceProvider.GetRequiredService(); + + var provider = serviceProvider.GetRequiredService() as LoggerProviderSdk; + + Assert.NotNull(provider); + + var resource = provider!.Resource; + + Assert.NotNull(resource); + + Assert.Contains(resource.Attributes, kvp => kvp.Key == "service.name"); + Assert.Contains(resource.Attributes, kvp => kvp.Key == "service.instance.id"); + Assert.Contains(resource.Attributes, kvp => kvp.Key == "key1"); + Assert.Contains(resource.Attributes, kvp => kvp.Key == "key2"); + } + + private sealed class WrappedLoggerProvider : LoggerProvider + { + public bool Disposed { get; private set; } + + protected override void Dispose(bool disposing) + { + this.Disposed = true; + + base.Dispose(disposing); + } + } + + private sealed class CustomProcessor : BaseProcessor + { + public CustomProcessor(int? id = null) + { + this.Id = id; + InstanceCount++; + } + + public static int InstanceCount { get; set; } + + public int? Id { get; } + + public bool Disposed { get; private set; } + + public TestClass? TestClass { get; set; } + + protected override void Dispose(bool disposing) + { + this.Disposed = true; + + base.Dispose(disposing); + } + } + + private sealed class TestClass + { + } } diff --git a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj index 199db4b6e4b..9d3ba6e6bc9 100644 --- a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj +++ b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj @@ -13,10 +13,8 @@ + - - -