diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index e8ddd8a3c72..ebe1cafdbaa 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -14,6 +14,13 @@ are now configurable via the `MetricReaderOptions`. ([#2717](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2717)) +* Exporter bug fix to not throw exceptions from Export method. + ([#2915](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2915)) + +* OTLP LogExporter modified to not drop the whole batch if a single log from the + batch is invalid. + ([#2934](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2934)) + ## 1.2.0-rc2 Released 2022-Feb-02 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs index b797b2a79e7..dd806194ef0 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System; using System.Runtime.CompilerServices; using Google.Protobuf; using Google.Protobuf.Collections; @@ -43,80 +44,84 @@ internal static void AddBatch( var instrumentationLibraryLogs = new OtlpLogs.InstrumentationLibraryLogs(); resourceLogs.InstrumentationLibraryLogs.Add(instrumentationLibraryLogs); - foreach (var item in logRecordBatch) + foreach (var logRecord in logRecordBatch) { - var logRecord = item.ToOtlpLog(); - if (logRecord == null) + var otlpLogRecord = logRecord.ToOtlpLog(); + if (otlpLogRecord != null) { - OpenTelemetryProtocolExporterEventSource.Log.CouldNotTranslateLogRecord( - nameof(LogRecordExtensions), - nameof(AddBatch)); - continue; + instrumentationLibraryLogs.Logs.Add(otlpLogRecord); } - - instrumentationLibraryLogs.Logs.Add(logRecord); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) { - var otlpLogRecord = new OtlpLogs.LogRecord + OtlpLogs.LogRecord otlpLogRecord = null; + + try { - TimeUnixNano = (ulong)logRecord.Timestamp.ToUnixTimeNanoseconds(), - Name = logRecord.CategoryName, + otlpLogRecord = new OtlpLogs.LogRecord + { + TimeUnixNano = (ulong)logRecord.Timestamp.ToUnixTimeNanoseconds(), + Name = logRecord.CategoryName, - // TODO: Devise mapping of LogLevel to SeverityNumber - // See: https://github.com/open-telemetry/opentelemetry-proto/blob/bacfe08d84e21fb2a779e302d12e8dfeb67e7b86/opentelemetry/proto/logs/v1/logs.proto#L100-L102 - SeverityText = logRecord.LogLevel.ToString(), - }; + // TODO: Devise mapping of LogLevel to SeverityNumber + // See: https://github.com/open-telemetry/opentelemetry-proto/blob/bacfe08d84e21fb2a779e302d12e8dfeb67e7b86/opentelemetry/proto/logs/v1/logs.proto#L100-L102 + SeverityText = logRecord.LogLevel.ToString(), + }; - if (logRecord.FormattedMessage != null) - { - otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = logRecord.FormattedMessage }; - } + if (logRecord.FormattedMessage != null) + { + otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = logRecord.FormattedMessage }; + } - if (logRecord.StateValues != null) - { - foreach (var stateValue in logRecord.StateValues) + if (logRecord.StateValues != null) { - var otlpAttribute = stateValue.ToOtlpAttribute(); - otlpLogRecord.Attributes.Add(otlpAttribute); + foreach (var stateValue in logRecord.StateValues) + { + var otlpAttribute = stateValue.ToOtlpAttribute(); + otlpLogRecord.Attributes.Add(otlpAttribute); + } } - } - if (logRecord.EventId.Id != default) - { - otlpLogRecord.Attributes.AddIntAttribute(nameof(logRecord.EventId.Id), logRecord.EventId.Id); - } + if (logRecord.EventId.Id != default) + { + otlpLogRecord.Attributes.AddIntAttribute(nameof(logRecord.EventId.Id), logRecord.EventId.Id); + } - if (!string.IsNullOrEmpty(logRecord.EventId.Name)) - { - otlpLogRecord.Attributes.AddStringAttribute(nameof(logRecord.EventId.Name), logRecord.EventId.Name); - } + if (!string.IsNullOrEmpty(logRecord.EventId.Name)) + { + otlpLogRecord.Attributes.AddStringAttribute(nameof(logRecord.EventId.Name), logRecord.EventId.Name); + } - if (logRecord.Exception != null) - { - otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name); - otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message); - otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString()); - } + if (logRecord.Exception != null) + { + otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name); + otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message); + otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString()); + } - if (logRecord.TraceId != default && logRecord.SpanId != default) - { - byte[] traceIdBytes = new byte[16]; - byte[] spanIdBytes = new byte[8]; + if (logRecord.TraceId != default && logRecord.SpanId != default) + { + byte[] traceIdBytes = new byte[16]; + byte[] spanIdBytes = new byte[8]; - logRecord.TraceId.CopyTo(traceIdBytes); - logRecord.SpanId.CopyTo(spanIdBytes); + logRecord.TraceId.CopyTo(traceIdBytes); + logRecord.SpanId.CopyTo(spanIdBytes); - otlpLogRecord.TraceId = UnsafeByteOperations.UnsafeWrap(traceIdBytes); - otlpLogRecord.SpanId = UnsafeByteOperations.UnsafeWrap(spanIdBytes); - otlpLogRecord.Flags = (uint)logRecord.TraceFlags; - } + otlpLogRecord.TraceId = UnsafeByteOperations.UnsafeWrap(traceIdBytes); + otlpLogRecord.SpanId = UnsafeByteOperations.UnsafeWrap(spanIdBytes); + otlpLogRecord.Flags = (uint)logRecord.TraceFlags; + } - // TODO: Add additional attributes from scope and state - // Might make sense to take an approach similar to https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/897b734aa5ea9992538f04f6ea6871fe211fa903/src/OpenTelemetry.Contrib.Preview/Internal/DefaultLogStateConverter.cs + // TODO: Add additional attributes from scope and state + // Might make sense to take an approach similar to https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/897b734aa5ea9992538f04f6ea6871fe211fa903/src/OpenTelemetry.Contrib.Preview/Internal/DefaultLogStateConverter.cs + } + catch (Exception ex) + { + OpenTelemetryProtocolExporterEventSource.Log.CouldNotTranslateLogRecord(ex.Message); + } return otlpLogRecord; } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs index 2e46de5c651..95d2aae5c8e 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs @@ -74,10 +74,10 @@ public void UnsupportedProtocol(string protocol) this.WriteEvent(8, protocol); } - [Event(9, Message = "Could not translate LogRecord from class '{0}' and method '{1}', log will not be exported.", Level = EventLevel.Informational)] - public void CouldNotTranslateLogRecord(string className, string methodName) + [Event(9, Message = "Could not translate LogRecord due to Exception: '{0}'. Log will not be exported.", Level = EventLevel.Warning)] + public void CouldNotTranslateLogRecord(string exceptionMessage) { - this.WriteEvent(9, className, methodName); + this.WriteEvent(9, exceptionMessage); } } } diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs index fe5b8d7b5a4..79001757e85 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs @@ -32,7 +32,7 @@ using Xunit; using OtlpCollector = Opentelemetry.Proto.Collector.Trace.V1; -namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests.Implementation.ExportClient +namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests { public class OtlpHttpTraceExportClientTests {