Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GenevaExporter] Add ability to export Log Exception using StackTrace #2422

Merged
merged 13 commits into from
Dec 18, 2024
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OpenTelemetry.Exporter.Geneva.ExceptionStackExportMode.ExportAsStackTraceString = 2 -> OpenTelemetry.Exporter.Geneva.ExceptionStackExportMode
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 20 additions & 3 deletions src/OpenTelemetry.Exporter.Geneva/ExceptionStackExportMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,36 @@
namespace OpenTelemetry.Exporter.Geneva;

/// <summary>
/// Contains the exception stack trace export mode defintions.
/// Defines modes for exporting exception stack traces. Currently applicable only to the Logs signal.
/// </summary>
public enum ExceptionStackExportMode
{
/// <summary>
/// Exception stack traces are dropped.
/// Exception stack traces are dropped and not exported.
/// </summary>
Drop,

/// <summary>
/// Exception stack traces are exported as strings.
/// Exports exception stack traces as a string using the <c>ToString()</c> implementation of the exception.
/// The output is formatted in a culture-agnostic manner and is primarily designed for human readability.
/// See <see href="https://learn.microsoft.com/dotnet/api/system.exception.tostring"/>.
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
/// <remarks>
/// Typically, <c>ToString()</c> includes information about inner exceptions and additional details,
/// such as the exception message. However, this behavior is not guaranteed, as custom exceptions
/// can override <c>ToString()</c> to return arbitrary content.
/// </remarks>
ExportAsString,

/// <summary>
/// Exports exception stack traces as a string using the <c>StackTrace</c> property of the exception.
/// See <see href="https://learn.microsoft.com/dotnet/api/system.exception.stacktrace"/>.
/// </summary>
/// <remarks>
/// This represents the raw stack trace and does not include inner exception details.
/// Note that the <c>StackTrace</c> property can also be overridden in custom exception implementations.
/// </remarks>
ExportAsStackTraceString,
cijothomas marked this conversation as resolved.
Show resolved Hide resolved

// ExportAsArrayOfStacks - future if stacks can be exported in more structured way
}
Original file line number Diff line number Diff line change
Expand Up @@ -419,20 +419,30 @@ internal ArraySegment<byte> 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)
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
{
cursor = MessagePackSerializer.SerializeAsciiString(buffer, cursor, "env_ex_stack");
cursor = MessagePackSerializer.SerializeUnicodeString(buffer, cursor, exceptionStack);
cntFields += 1;
}
}
}

MessagePackSerializer.WriteUInt16(buffer, idxMapSizePatch, cntFields);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading