diff --git a/src/OpenTelemetry.Exporter.Geneva/.publicApi/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Geneva/.publicApi/PublicAPI.Unshipped.txt index e69de29bb2..44dadc78df 100644 --- a/src/OpenTelemetry.Exporter.Geneva/.publicApi/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Geneva/.publicApi/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +OpenTelemetry.Exporter.Geneva.ExceptionStackExportMode.ExportAsStackTraceString = 2 -> OpenTelemetry.Exporter.Geneva.ExceptionStackExportMode \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md b/src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md index 5635ffc0c0..3fc87b0de5 100644 --- a/src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +* Added support for exporting exception stack traces using + `Exception.StackTrace`. This can be enabled via the + `ExceptionStackExportMode.ExportAsStackTraceString` enum. Applicable only to + the LogExporter. + ([#2422](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2422)) + ## 1.10.0 Released 2024-Nov-18 diff --git a/src/OpenTelemetry.Exporter.Geneva/ExceptionStackExportMode.cs b/src/OpenTelemetry.Exporter.Geneva/ExceptionStackExportMode.cs index 9030a32b9c..87b2ec20ae 100644 --- a/src/OpenTelemetry.Exporter.Geneva/ExceptionStackExportMode.cs +++ b/src/OpenTelemetry.Exporter.Geneva/ExceptionStackExportMode.cs @@ -4,19 +4,36 @@ namespace OpenTelemetry.Exporter.Geneva; /// -/// Contains the exception stack trace export mode defintions. +/// Defines modes for exporting exception stack traces. Currently applicable only to the Logs signal. /// public enum ExceptionStackExportMode { /// - /// Exception stack traces are dropped. + /// Exception stack traces are dropped and not exported. /// Drop, /// - /// Exception stack traces are exported as strings. + /// Exports exception stack traces as a string using the ToString() implementation of the exception. + /// The output is formatted in a culture-agnostic manner and is primarily designed for human readability. + /// See . /// + /// + /// Typically, ToString() includes information about inner exceptions and additional details, + /// such as the exception message. However, this behavior is not guaranteed, as custom exceptions + /// can override ToString() to return arbitrary content. + /// ExportAsString, + /// + /// Exports exception stack traces as a string using the StackTrace property of the exception. + /// See . + /// + /// + /// This represents the raw stack trace and does not include inner exception details. + /// Note that the StackTrace property can also be overridden in custom exception implementations. + /// + ExportAsStackTraceString, + // ExportAsArrayOfStacks - future if stacks can be exported in more structured way } diff --git a/src/OpenTelemetry.Exporter.Geneva/Internal/MsgPack/MsgPackLogExporter.cs b/src/OpenTelemetry.Exporter.Geneva/Internal/MsgPack/MsgPackLogExporter.cs index de39f6e7fd..ba3c9969c1 100644 --- a/src/OpenTelemetry.Exporter.Geneva/Internal/MsgPack/MsgPackLogExporter.cs +++ b/src/OpenTelemetry.Exporter.Geneva/Internal/MsgPack/MsgPackLogExporter.cs @@ -419,20 +419,30 @@ internal ArraySegment SerializeLogRecord(LogRecord logRecord) cursor = MessagePackSerializer.SerializeUnicodeString(buffer, cursor, logRecord.Exception.Message); cntFields += 1; + // The current approach relies on the existing trim + // capabilities which trims string in excess of STRING_SIZE_LIMIT_CHAR_COUNT + // TODO: Revisit this: + // 1. Trim it off based on how much more bytes are available + // before running out of limit instead of STRING_SIZE_LIMIT_CHAR_COUNT. + // 2. Trim smarter, by trimming the middle of stack, an + // keep top and bottom. if (this.exportExceptionStack == ExceptionStackExportMode.ExportAsString) { - // The current approach relies on the existing trim - // capabilities which trims string in excess of STRING_SIZE_LIMIT_CHAR_COUNT - // TODO: Revisit this: - // 1. Trim it off based on how much more bytes are available - // before running out of limit instead of STRING_SIZE_LIMIT_CHAR_COUNT. - // 2. Trim smarter, by trimming the middle of stack, an - // keep top and bottom. var exceptionStack = logRecord.Exception.ToInvariantString(); cursor = MessagePackSerializer.SerializeAsciiString(buffer, cursor, "env_ex_stack"); cursor = MessagePackSerializer.SerializeUnicodeString(buffer, cursor, exceptionStack); cntFields += 1; } + else if (this.exportExceptionStack == ExceptionStackExportMode.ExportAsStackTraceString) + { + var exceptionStack = logRecord.Exception.StackTrace; + if (exceptionStack != null) + { + cursor = MessagePackSerializer.SerializeAsciiString(buffer, cursor, "env_ex_stack"); + cursor = MessagePackSerializer.SerializeUnicodeString(buffer, cursor, exceptionStack); + cntFields += 1; + } + } } MessagePackSerializer.WriteUInt16(buffer, idxMapSizePatch, cntFields); diff --git a/src/OpenTelemetry.Exporter.Geneva/Internal/Tld/TldLogExporter.cs b/src/OpenTelemetry.Exporter.Geneva/Internal/Tld/TldLogExporter.cs index 1e28710271..9f31da3f01 100644 --- a/src/OpenTelemetry.Exporter.Geneva/Internal/Tld/TldLogExporter.cs +++ b/src/OpenTelemetry.Exporter.Geneva/Internal/Tld/TldLogExporter.cs @@ -260,6 +260,15 @@ internal EventBuilder SerializeLogRecord(LogRecord logRecord) eb.AddCountedAnsiString("ext_ex_stack", exceptionStack, Encoding.UTF8, 0, Math.Min(exceptionStack.Length, StringLengthLimit)); partAFieldsCount++; } + else if (this.exceptionStackExportMode == ExceptionStackExportMode.ExportAsStackTraceString) + { + var stackTrace = logRecord.Exception.StackTrace; + if (stackTrace != null) + { + eb.AddCountedAnsiString("ext_ex_stack", stackTrace, Encoding.UTF8, 0, Math.Min(stackTrace.Length, StringLengthLimit)); + partAFieldsCount++; + } + } } eb.SetStructFieldCount(partAFieldsCountPatch, partAFieldsCount);