From a2017af23b717a7fc579aa637f5c2706b053324e Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 29 Sep 2020 15:46:23 -0700 Subject: [PATCH 1/9] add log processor --- docs/logs/getting-started/MyProcessor.cs | 85 ++++++++ docs/logs/getting-started/Program.cs | 25 ++- .../getting-started/getting-started.csproj | 15 +- .../Logs/CompositeLogProcessor.cs | 189 ++++++++++++++++++ src/OpenTelemetry/Logs/LogProcessor.cs | 183 +++++++++++++++++ src/OpenTelemetry/Logs/LogRecord.cs | 34 ++++ .../Logs/LoggerProviderBuilder.cs | 50 +++++ src/OpenTelemetry/Logs/OpenTelemetryLogger.cs | 51 ++--- .../Logs/OpenTelemetryLoggerOptions.cs | 20 ++ .../Logs/OpenTelemetryLoggerProvider.cs | 65 +++++- src/OpenTelemetry/Sdk.cs | 10 + 11 files changed, 683 insertions(+), 44 deletions(-) create mode 100644 docs/logs/getting-started/MyProcessor.cs create mode 100644 src/OpenTelemetry/Logs/CompositeLogProcessor.cs create mode 100644 src/OpenTelemetry/Logs/LogProcessor.cs create mode 100644 src/OpenTelemetry/Logs/LogRecord.cs create mode 100644 src/OpenTelemetry/Logs/LoggerProviderBuilder.cs diff --git a/docs/logs/getting-started/MyProcessor.cs b/docs/logs/getting-started/MyProcessor.cs new file mode 100644 index 00000000000..cc105ce941a --- /dev/null +++ b/docs/logs/getting-started/MyProcessor.cs @@ -0,0 +1,85 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using OpenTelemetry; +using OpenTelemetry.Logs; + +internal class MyProcessor : LogProcessor +{ + private readonly string name; + + public MyProcessor(string name = "MyProcessor") + { + this.name = name; + } + + public override void OnLog(in LogRecord record) + { + var state = record.State; + + if (state is IReadOnlyCollection> dict) + { + var isUnstructuredLog = dict.Count == 1; + + if (isUnstructuredLog) + { + foreach (var entry in dict) + { + Console.WriteLine($"{record.Timestamp:yyyy-MM-ddTHH:mm:ss.fffffffZ} {record.CategoryName}({record.LogLevel}, Id={record.EventId}): {entry.Value}"); + } + } + else + { + Console.WriteLine($"{record.Timestamp:yyyy-MM-ddTHH:mm:ss.fffffffZ} {record.CategoryName}({record.LogLevel}, Id={record.EventId}):"); + foreach (var entry in dict) + { + if (string.Equals(entry.Key, "{OriginalFormat}", StringComparison.Ordinal)) + { + Console.WriteLine($" $format: {entry.Value}"); + continue; + } + + Console.WriteLine($" {entry.Key}: {entry.Value}"); + } + } + + if (record.Exception != null) + { + Console.WriteLine($" $exception: {record.Exception}"); + } + } + } + + protected override bool OnForceFlush(int timeoutMilliseconds) + { + Console.WriteLine($"{this.name}.OnForceFlush({timeoutMilliseconds})"); + return true; + } + + protected override bool OnShutdown(int timeoutMilliseconds) + { + Console.WriteLine($"{this.name}.OnShutdown({timeoutMilliseconds})"); + return true; + } + + protected override void Dispose(bool disposing) + { + Console.WriteLine($"{this.name}.Dispose({disposing})"); + } +} diff --git a/docs/logs/getting-started/Program.cs b/docs/logs/getting-started/Program.cs index 23f3924d057..a5047440105 100644 --- a/docs/logs/getting-started/Program.cs +++ b/docs/logs/getting-started/Program.cs @@ -15,17 +15,40 @@ // using System.Collections.Generic; +#if NETCOREAPP2_1 +using Microsoft.Extensions.DependencyInjection; +#endif using Microsoft.Extensions.Logging; +using OpenTelemetry; public class Program { public static void Main() { + /* + The OpenTelemetry style: + + using var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddProcessor(new MyProcessor()) + .Build(); + var logger = loggerProvider.CreateLogger("MyLogger"); + */ + +#if NETCOREAPP2_1 + var serviceCollection = new ServiceCollection().AddLogging(builder => +#else using var loggerFactory = LoggerFactory.Create(builder => +#endif { - builder.AddOpenTelemetry(); + builder.AddOpenTelemetry(options => options.AddProcessor(new MyProcessor())); }); + +#if NETCOREAPP2_1 + using var serviceProvider = serviceCollection.BuildServiceProvider(); + var logger = serviceProvider.GetRequiredService>(); +#else var logger = loggerFactory.CreateLogger(); +#endif // unstructured log logger.LogInformation("Hello, World!"); diff --git a/docs/logs/getting-started/getting-started.csproj b/docs/logs/getting-started/getting-started.csproj index fed46f5b594..c058d44c7ad 100644 --- a/docs/logs/getting-started/getting-started.csproj +++ b/docs/logs/getting-started/getting-started.csproj @@ -1,6 +1,19 @@ + + Exe + netcoreapp3.1 + + - + + + + + + + + + diff --git a/src/OpenTelemetry/Logs/CompositeLogProcessor.cs b/src/OpenTelemetry/Logs/CompositeLogProcessor.cs new file mode 100644 index 00000000000..7e81efcf184 --- /dev/null +++ b/src/OpenTelemetry/Logs/CompositeLogProcessor.cs @@ -0,0 +1,189 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + public class CompositeLogProcessor : LogProcessor + { + private DoublyLinkedListNode head; + private DoublyLinkedListNode tail; + private bool disposed; + + public CompositeLogProcessor(IEnumerable processors) + { + if (processors == null) + { + throw new ArgumentNullException(nameof(processors)); + } + + using var iter = processors.GetEnumerator(); + + if (!iter.MoveNext()) + { + throw new ArgumentException($"{nameof(processors)} collection is empty"); + } + + this.head = new DoublyLinkedListNode(iter.Current); + this.tail = this.head; + + while (iter.MoveNext()) + { + this.AddProcessor(iter.Current); + } + } + + public CompositeLogProcessor AddProcessor(LogProcessor processor) + { + if (processor == null) + { + throw new ArgumentNullException(nameof(processor)); + } + + var node = new DoublyLinkedListNode(processor) + { + Previous = this.tail, + }; + this.tail.Next = node; + this.tail = node; + + return this; + } + + /// + public override void OnLog(in LogRecord record) + { + var cur = this.head; + + while (cur != null) + { + cur.Value.OnLog(record); + cur = cur.Next; + } + } + + /// + protected override bool OnForceFlush(int timeoutMilliseconds) + { + var cur = this.head; + + var sw = Stopwatch.StartNew(); + + while (cur != null) + { + if (timeoutMilliseconds == Timeout.Infinite) + { + _ = cur.Value.ForceFlush(Timeout.Infinite); + } + else + { + var timeout = (long)timeoutMilliseconds - sw.ElapsedMilliseconds; + + if (timeout <= 0) + { + return false; + } + + var succeeded = cur.Value.ForceFlush((int)timeout); + + if (!succeeded) + { + return false; + } + } + + cur = cur.Next; + } + + return true; + } + + /// + protected override bool OnShutdown(int timeoutMilliseconds) + { + var cur = this.head; + var result = true; + var sw = Stopwatch.StartNew(); + + while (cur != null) + { + if (timeoutMilliseconds == Timeout.Infinite) + { + result = cur.Value.Shutdown(Timeout.Infinite) && result; + } + else + { + var timeout = (long)timeoutMilliseconds - sw.ElapsedMilliseconds; + + // notify all the processors, even if we run overtime + result = cur.Value.Shutdown((int)Math.Max(timeout, 0)) && result; + } + + cur = cur.Next; + } + + return result; + } + + protected override void Dispose(bool disposing) + { + if (this.disposed) + { + return; + } + + if (disposing) + { + var cur = this.head; + + while (cur != null) + { + try + { + cur.Value?.Dispose(); + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.Dispose), ex); + } + + cur = cur.Next; + } + } + + this.disposed = true; + } + + private class DoublyLinkedListNode + { + public readonly T Value; + + public DoublyLinkedListNode(T value) + { + this.Value = value; + } + + public DoublyLinkedListNode Previous { get; set; } + + public DoublyLinkedListNode Next { get; set; } + } + } +} diff --git a/src/OpenTelemetry/Logs/LogProcessor.cs b/src/OpenTelemetry/Logs/LogProcessor.cs new file mode 100644 index 00000000000..ca2ebbbca3f --- /dev/null +++ b/src/OpenTelemetry/Logs/LogProcessor.cs @@ -0,0 +1,183 @@ +// +// 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.Threading; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs +{ + /// + /// Log processor base class. + /// + public abstract class LogProcessor : IDisposable + { + private int shutdownCount; + + /// + /// Called synchronously when a is recorded. + /// + /// + /// The log record. + /// + /// + /// This function is called synchronously on the thread which generated + /// the log record. This function should be thread-safe, and should not + /// block indefinitely or throw exceptions. + /// + public virtual void OnLog(in LogRecord record) + { + } + + /// + /// Flushes the , blocks the current + /// thread until flush completed, shutdown signaled or timed out. + /// + /// + /// The number of milliseconds to wait, or Timeout.Infinite to + /// wait indefinitely. + /// + /// + /// Returns true when flush succeeded; otherwise, false. + /// + /// + /// Thrown when the timeoutMilliseconds is smaller than -1. + /// + /// + /// This function guarantees thread-safety. + /// + public bool ForceFlush(int timeoutMilliseconds = Timeout.Infinite) + { + if (timeoutMilliseconds < 0 && timeoutMilliseconds != Timeout.Infinite) + { + throw new ArgumentOutOfRangeException(nameof(timeoutMilliseconds)); + } + + try + { + return this.OnForceFlush(timeoutMilliseconds); + } + catch (Exception ex) + { + // TODO: replace this with a better internal logging + OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.ForceFlush), ex); + return false; + } + } + + /// + /// Attempts to shutdown the , blocks + /// the current thread until shutdown completed or timed out. + /// + /// + /// The number 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 bool Shutdown(int timeoutMilliseconds = Timeout.Infinite) + { + if (timeoutMilliseconds < 0 && timeoutMilliseconds != Timeout.Infinite) + { + throw new ArgumentOutOfRangeException(nameof(timeoutMilliseconds)); + } + + if (Interlocked.Increment(ref this.shutdownCount) > 1) + { + return false; // shutdown already called + } + + try + { + return this.OnShutdown(timeoutMilliseconds); + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.Shutdown), ex); + return false; + } + } + + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Called by ForceFlush. This function should block the current + /// thread until flush completed, shutdown signaled or timed out. + /// + /// + /// The number of milliseconds to wait, or Timeout.Infinite to + /// wait indefinitely. + /// + /// + /// Returns true when flush succeeded; otherwise, false. + /// + /// + /// This function is called synchronously on the thread which called + /// ForceFlush. This function should be thread-safe, and should + /// not throw exceptions. + /// + protected virtual bool OnForceFlush(int timeoutMilliseconds) + { + return true; + } + + /// + /// Called by Shutdown. This function should block the current + /// thread until shutdown completed or timed out. + /// + /// + /// The number of milliseconds to wait, or Timeout.Infinite to + /// wait indefinitely. + /// + /// + /// Returns true when shutdown succeeded; otherwise, false. + /// + /// + /// This function is called synchronously on the thread which made the + /// first call to Shutdown. This function should not throw + /// exceptions. + /// + protected virtual bool OnShutdown(int timeoutMilliseconds) + { + return true; + } + + /// + /// Releases the unmanaged resources used by this class and optionally + /// releases the managed resources. + /// + /// + /// to release both managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + } + } +} diff --git a/src/OpenTelemetry/Logs/LogRecord.cs b/src/OpenTelemetry/Logs/LogRecord.cs new file mode 100644 index 00000000000..80128f37034 --- /dev/null +++ b/src/OpenTelemetry/Logs/LogRecord.cs @@ -0,0 +1,34 @@ +// +// 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 Microsoft.Extensions.Logging; + +namespace OpenTelemetry.Logs +{ + /// + /// Log record base class. + /// + public struct LogRecord + { + public DateTime Timestamp; + public string CategoryName; + public LogLevel LogLevel; + public EventId EventId; + public object State; + public Exception Exception; + } +} diff --git a/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs b/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs new file mode 100644 index 00000000000..7a02fe95921 --- /dev/null +++ b/src/OpenTelemetry/Logs/LoggerProviderBuilder.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. +// + +using System; +using System.Collections.Generic; + +namespace OpenTelemetry.Logs +{ + /// + /// Build OpenTelemetryLoggerProvider with Processors. + /// + public class LoggerProviderBuilder + { + private OpenTelemetryLoggerOptions options; + + internal LoggerProviderBuilder() + { + this.options = new OpenTelemetryLoggerOptions(); + } + + /// + /// Adds processor to the provider. + /// + /// Log processor to add. + /// Returns for chaining. + public LoggerProviderBuilder AddProcessor(LogProcessor processor) + { + this.options.AddProcessor(processor); + return this; + } + + public OpenTelemetryLoggerProvider Build() + { + return new OpenTelemetryLoggerProvider(this.options); + } + } +} diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs b/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs index 1f3fd82f9ea..3f6394a6eef 100644 --- a/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs +++ b/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs @@ -16,7 +16,6 @@ #if NETSTANDARD2_0 using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using Microsoft.Extensions.Logging; @@ -26,15 +25,12 @@ namespace OpenTelemetry.Logs internal class OpenTelemetryLogger : ILogger { private readonly string categoryName; + private readonly OpenTelemetryLoggerProvider provider; - internal OpenTelemetryLogger(string categoryName, OpenTelemetryLoggerOptions options) + internal OpenTelemetryLogger(string categoryName, OpenTelemetryLoggerProvider provider) { this.categoryName = categoryName ?? throw new ArgumentNullException(nameof(categoryName)); - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } + this.provider = provider ?? throw new ArgumentNullException(nameof(provider)); } internal IExternalScopeProvider ScopeProvider { get; set; } @@ -46,40 +42,17 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except return; } - var timestamp = DateTime.UtcNow; - - if (state is IReadOnlyCollection> dict) + var record = new LogRecord { - var isUnstructuredLog = dict.Count == 1; + Timestamp = DateTime.UtcNow, + CategoryName = this.categoryName, + LogLevel = logLevel, + EventId = eventId, + State = state, + Exception = exception, + }; - // TODO: remove the console output after finished the plumbing work to log processors/exporters - if (isUnstructuredLog) - { - foreach (var entry in dict) - { - Console.WriteLine($"{this.categoryName}({logLevel}, Id={eventId}): {entry.Value}"); - } - } - else - { - Console.WriteLine($"{this.categoryName}({logLevel}, Id={eventId}):"); - foreach (var entry in dict) - { - if (string.Equals(entry.Key, "{OriginalFormat}", StringComparison.Ordinal)) - { - Console.WriteLine($" $format: {entry.Value}"); - continue; - } - - Console.WriteLine($" {entry.Key}: {entry.Value}"); - } - } - - if (exception != null) - { - Console.WriteLine($" $exception: {exception}"); - } - } + this.provider.Processor?.OnLog(record); } public bool IsEnabled(LogLevel logLevel) diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs b/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs index f44baf424f2..d8f92f67dd1 100644 --- a/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs +++ b/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs @@ -15,12 +15,32 @@ // #if NETSTANDARD2_0 +using System; +using System.Collections.Generic; using Microsoft.Extensions.Logging; namespace OpenTelemetry.Logs { public class OpenTelemetryLoggerOptions { + public readonly List Processors = new List(); + + /// + /// Adds processor to the provider. + /// + /// Log processor to add. + /// Returns for chaining. + public OpenTelemetryLoggerOptions AddProcessor(LogProcessor processor) + { + if (processor == null) + { + throw new ArgumentNullException(nameof(processor)); + } + + this.Processors.Add(processor); + + return this; + } } } #endif diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs b/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs index 66aae355095..4d6f0649fe2 100644 --- a/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs +++ b/src/OpenTelemetry/Logs/OpenTelemetryLoggerProvider.cs @@ -25,14 +25,26 @@ namespace OpenTelemetry.Logs [ProviderAlias("OpenTelemetry")] public class OpenTelemetryLoggerProvider : ILoggerProvider, ISupportExternalScope { - private readonly IOptionsMonitor options; + internal LogProcessor Processor; + private readonly OpenTelemetryLoggerOptions options; private readonly IDictionary loggers; + private bool disposed; private IExternalScopeProvider scopeProvider; public OpenTelemetryLoggerProvider(IOptionsMonitor options) + : this(options.CurrentValue) { - this.options = options; + } + + internal OpenTelemetryLoggerProvider(OpenTelemetryLoggerOptions options) + { + this.options = options ?? throw new ArgumentNullException(nameof(options)); this.loggers = new Dictionary(StringComparer.Ordinal); + + foreach (var processor in options.Processors) + { + this.AddProcessor(processor); + } } internal IExternalScopeProvider ScopeProvider @@ -65,14 +77,61 @@ public ILogger CreateLogger(string categoryName) return logger; } - logger = new OpenTelemetryLogger(categoryName, this.options.CurrentValue); + logger = new OpenTelemetryLogger(categoryName, this); this.loggers.Add(categoryName, logger); return logger; } } + /// public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + internal OpenTelemetryLoggerProvider AddProcessor(LogProcessor processor) + { + if (processor == null) + { + throw new ArgumentNullException(nameof(processor)); + } + + if (this.Processor == null) + { + this.Processor = processor; + } + else if (this.Processor is CompositeLogProcessor compositeProcessor) + { + compositeProcessor.AddProcessor(processor); + } + else + { + this.Processor = new CompositeLogProcessor(new[] + { + this.Processor, + processor, + }); + } + + return this; + } + + protected void Dispose(bool disposing) + { + if (this.disposed) + { + return; + } + + if (disposing) + { + // Wait for up to 5 seconds grace period + this.Processor?.Shutdown(5000); + this.Processor?.Dispose(); + } + + this.disposed = true; } } } diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index 30fc0e3a4e9..bb9fd0ba6eb 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Trace; @@ -29,6 +30,15 @@ public static class Sdk /// public static bool SuppressInstrumentation => SuppressInstrumentationScope.IsSuppressed; + /// + /// Creates LoggerProviderBuilder which should be used to build LoggerProvider. + /// + /// LoggerProviderBuilder instance, which should be used to build LoggerProvider. + public static LoggerProviderBuilder CreateLoggerProviderBuilder() + { + return new LoggerProviderBuilder(); + } + /// /// Creates MeterProviderBuilder which should be used to build MeterProvider. /// From ed01a3ebd310acb8dc33a84888209a520e0207d0 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 29 Sep 2020 16:01:22 -0700 Subject: [PATCH 2/9] fix changelog --- src/OpenTelemetry.Api/CHANGELOG.md | 3 --- src/OpenTelemetry/CHANGELOG.md | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index 823e7c21b8f..0575e5078d5 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -2,9 +2,6 @@ ## Unreleased -* Added `ILogger`/`Microsoft.Extensions.Logging` integration - ([#1308](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1308)) - ## 0.6.0-beta.1 Released 2020-Sep-15 diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 73658d90e78..e4712733326 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -10,6 +10,9 @@ * Renamed `SamplingDecision` options (`NotRecord` to `Drop`, `Record` to `RecordOnly`, and `RecordAndSampled` to `RecordAndSample`) ([#1297](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1297)) +* Added `ILogger`/`Microsoft.Extensions.Logging` integration + ([#1308](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1308)) + ([#1315](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1315)) ## 0.6.0-beta.1 From decd4b7b2819a5c191623ee7602fed45697b45ad Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 29 Sep 2020 16:09:00 -0700 Subject: [PATCH 3/9] macros --- src/OpenTelemetry/Logs/CompositeLogProcessor.cs | 2 ++ src/OpenTelemetry/Logs/LogProcessor.cs | 2 ++ src/OpenTelemetry/Logs/LogRecord.cs | 2 ++ src/OpenTelemetry/Logs/LoggerProviderBuilder.cs | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/OpenTelemetry/Logs/CompositeLogProcessor.cs b/src/OpenTelemetry/Logs/CompositeLogProcessor.cs index 7e81efcf184..a2249286491 100644 --- a/src/OpenTelemetry/Logs/CompositeLogProcessor.cs +++ b/src/OpenTelemetry/Logs/CompositeLogProcessor.cs @@ -14,6 +14,7 @@ // limitations under the License. // +#if NETSTANDARD2_0 using System; using System.Collections.Generic; using System.Diagnostics; @@ -187,3 +188,4 @@ public DoublyLinkedListNode(T value) } } } +#endif diff --git a/src/OpenTelemetry/Logs/LogProcessor.cs b/src/OpenTelemetry/Logs/LogProcessor.cs index ca2ebbbca3f..746be844d3d 100644 --- a/src/OpenTelemetry/Logs/LogProcessor.cs +++ b/src/OpenTelemetry/Logs/LogProcessor.cs @@ -14,6 +14,7 @@ // limitations under the License. // +#if NETSTANDARD2_0 using System; using System.Threading; using OpenTelemetry.Internal; @@ -181,3 +182,4 @@ protected virtual void Dispose(bool disposing) } } } +#endif diff --git a/src/OpenTelemetry/Logs/LogRecord.cs b/src/OpenTelemetry/Logs/LogRecord.cs index 80128f37034..bfea41a719a 100644 --- a/src/OpenTelemetry/Logs/LogRecord.cs +++ b/src/OpenTelemetry/Logs/LogRecord.cs @@ -14,6 +14,7 @@ // limitations under the License. // +#if NETSTANDARD2_0 using System; using Microsoft.Extensions.Logging; @@ -32,3 +33,4 @@ public struct LogRecord public Exception Exception; } } +#endif diff --git a/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs b/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs index 7a02fe95921..cc6a3a889aa 100644 --- a/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs +++ b/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs @@ -14,6 +14,7 @@ // limitations under the License. // +#if NETSTANDARD2_0 using System; using System.Collections.Generic; @@ -48,3 +49,4 @@ public OpenTelemetryLoggerProvider Build() } } } +#endif From e4dd3ce9a7ae4d2c1f0eda7cea69587903d57986 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 29 Sep 2020 16:30:50 -0700 Subject: [PATCH 4/9] more conditional compilations --- src/OpenTelemetry/Sdk.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index bb9fd0ba6eb..2cb3aa8cf4a 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -14,7 +14,9 @@ // limitations under the License. // +#if NETSTANDARD2_0 using OpenTelemetry.Logs; +#endif using OpenTelemetry.Metrics; using OpenTelemetry.Trace; @@ -30,6 +32,7 @@ public static class Sdk /// public static bool SuppressInstrumentation => SuppressInstrumentationScope.IsSuppressed; +#if NETSTANDARD2_0 /// /// Creates LoggerProviderBuilder which should be used to build LoggerProvider. /// @@ -38,6 +41,7 @@ public static LoggerProviderBuilder CreateLoggerProviderBuilder() { return new LoggerProviderBuilder(); } +#endif /// /// Creates MeterProviderBuilder which should be used to build MeterProvider. From 817693166dbead3ff8791f42d534c2a946ceab1a Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 29 Sep 2020 17:51:57 -0700 Subject: [PATCH 5/9] improve struct --- src/OpenTelemetry/Logs/LogRecord.cs | 29 ++++++++++++++----- src/OpenTelemetry/Logs/OpenTelemetryLogger.cs | 10 +------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/OpenTelemetry/Logs/LogRecord.cs b/src/OpenTelemetry/Logs/LogRecord.cs index bfea41a719a..a4d7499f2d8 100644 --- a/src/OpenTelemetry/Logs/LogRecord.cs +++ b/src/OpenTelemetry/Logs/LogRecord.cs @@ -23,14 +23,29 @@ namespace OpenTelemetry.Logs /// /// Log record base class. /// - public struct LogRecord + public readonly struct LogRecord { - public DateTime Timestamp; - public string CategoryName; - public LogLevel LogLevel; - public EventId EventId; - public object State; - public Exception Exception; + internal LogRecord(DateTime timestamp, string categoryName, LogLevel logLevel, EventId eventId, object state, Exception exception) + { + this.Timestamp = timestamp; + this.CategoryName = categoryName; + this.LogLevel = logLevel; + this.EventId = eventId; + this.State = state; + this.Exception = exception; + } + + public DateTime Timestamp { get; } + + public string CategoryName { get; } + + public LogLevel LogLevel { get; } + + public EventId EventId { get; } + + public object State { get; } + + public Exception Exception { get; } } } #endif diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs b/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs index 3f6394a6eef..1934f36f460 100644 --- a/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs +++ b/src/OpenTelemetry/Logs/OpenTelemetryLogger.cs @@ -42,15 +42,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except return; } - var record = new LogRecord - { - Timestamp = DateTime.UtcNow, - CategoryName = this.categoryName, - LogLevel = logLevel, - EventId = eventId, - State = state, - Exception = exception, - }; + var record = new LogRecord(DateTime.UtcNow, this.categoryName, logLevel, eventId, state, exception); this.provider.Processor?.OnLog(record); } From d6ccc71b331ac7b9cc59959115d8572fa53348f3 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Wed, 30 Sep 2020 19:34:31 -0700 Subject: [PATCH 6/9] remove duplicated stuff --- docs/logs/getting-started/getting-started.csproj | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/logs/getting-started/getting-started.csproj b/docs/logs/getting-started/getting-started.csproj index c058d44c7ad..7936ba12eb9 100644 --- a/docs/logs/getting-started/getting-started.csproj +++ b/docs/logs/getting-started/getting-started.csproj @@ -1,6 +1,5 @@ - Exe netcoreapp3.1 @@ -8,12 +7,12 @@ - - - - + + + + From 8118e5777ed44e6bb48e64e0de5b7d1428303c01 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Sat, 3 Oct 2020 23:46:46 -0700 Subject: [PATCH 7/9] remove Sdk.CreateLoggerProviderBuilder --- docs/logs/getting-started/Program.cs | 9 --------- .../Logs/OpenTelemetryLoggerOptions.cs | 2 +- src/OpenTelemetry/Sdk.cs | 14 -------------- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/docs/logs/getting-started/Program.cs b/docs/logs/getting-started/Program.cs index a5047440105..b932c2be658 100644 --- a/docs/logs/getting-started/Program.cs +++ b/docs/logs/getting-started/Program.cs @@ -25,15 +25,6 @@ public class Program { public static void Main() { - /* - The OpenTelemetry style: - - using var loggerProvider = Sdk.CreateLoggerProviderBuilder() - .AddProcessor(new MyProcessor()) - .Build(); - var logger = loggerProvider.CreateLogger("MyLogger"); - */ - #if NETCOREAPP2_1 var serviceCollection = new ServiceCollection().AddLogging(builder => #else diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs b/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs index d8f92f67dd1..ffd2ee9a85e 100644 --- a/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs +++ b/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs @@ -23,7 +23,7 @@ namespace OpenTelemetry.Logs { public class OpenTelemetryLoggerOptions { - public readonly List Processors = new List(); + internal readonly List Processors = new List(); /// /// Adds processor to the provider. diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index 2cb3aa8cf4a..30fc0e3a4e9 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -14,9 +14,6 @@ // limitations under the License. // -#if NETSTANDARD2_0 -using OpenTelemetry.Logs; -#endif using OpenTelemetry.Metrics; using OpenTelemetry.Trace; @@ -32,17 +29,6 @@ public static class Sdk /// public static bool SuppressInstrumentation => SuppressInstrumentationScope.IsSuppressed; -#if NETSTANDARD2_0 - /// - /// Creates LoggerProviderBuilder which should be used to build LoggerProvider. - /// - /// LoggerProviderBuilder instance, which should be used to build LoggerProvider. - public static LoggerProviderBuilder CreateLoggerProviderBuilder() - { - return new LoggerProviderBuilder(); - } -#endif - /// /// Creates MeterProviderBuilder which should be used to build MeterProvider. /// From 70b34295450483d5535f9ed4a2fb494cf99dd61f Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Mon, 5 Oct 2020 09:08:20 -0700 Subject: [PATCH 8/9] clean up --- .../Logs/LoggerProviderBuilder.cs | 52 ------------------- .../Logs/OpenTelemetryLoggerOptions.cs | 4 +- 2 files changed, 2 insertions(+), 54 deletions(-) delete mode 100644 src/OpenTelemetry/Logs/LoggerProviderBuilder.cs diff --git a/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs b/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs deleted file mode 100644 index cc6a3a889aa..00000000000 --- a/src/OpenTelemetry/Logs/LoggerProviderBuilder.cs +++ /dev/null @@ -1,52 +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. -// - -#if NETSTANDARD2_0 -using System; -using System.Collections.Generic; - -namespace OpenTelemetry.Logs -{ - /// - /// Build OpenTelemetryLoggerProvider with Processors. - /// - public class LoggerProviderBuilder - { - private OpenTelemetryLoggerOptions options; - - internal LoggerProviderBuilder() - { - this.options = new OpenTelemetryLoggerOptions(); - } - - /// - /// Adds processor to the provider. - /// - /// Log processor to add. - /// Returns for chaining. - public LoggerProviderBuilder AddProcessor(LogProcessor processor) - { - this.options.AddProcessor(processor); - return this; - } - - public OpenTelemetryLoggerProvider Build() - { - return new OpenTelemetryLoggerProvider(this.options); - } - } -} -#endif diff --git a/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs b/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs index ffd2ee9a85e..46d65077e7f 100644 --- a/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs +++ b/src/OpenTelemetry/Logs/OpenTelemetryLoggerOptions.cs @@ -26,10 +26,10 @@ public class OpenTelemetryLoggerOptions internal readonly List Processors = new List(); /// - /// Adds processor to the provider. + /// Adds processor to the options. /// /// Log processor to add. - /// Returns for chaining. + /// Returns for chaining. public OpenTelemetryLoggerOptions AddProcessor(LogProcessor processor) { if (processor == null) From df1a3ee67a59d8f0b11ecce151a088f4fc16e41e Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Mon, 5 Oct 2020 10:02:26 -0700 Subject: [PATCH 9/9] update changelog --- src/OpenTelemetry.Api/CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index f45f0960e53..ab72592c345 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -2,8 +2,6 @@ ## Unreleased -* Added `ILogger`/`Microsoft.Extensions.Logging` integration - ([#1308](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1308)) * `IActivityTagEnumerator` is now `IActivityEnumerator`. Added `EnumerateLinks` extension method on `Activity` for retrieving links efficiently