Skip to content

Commit

Permalink
Require only one of exception.{type,message} for log exceptions (#182)
Browse files Browse the repository at this point in the history
* otlp: follow semconv for exception fields

otel semconv require that at lease one field between
exception.message or exception.type to be present on an application
exception.

To ensure we respect them we default on adding exception.type only
if has a value and defaulting exception.message to a constant
string when empty and no exception.type is present.

* otlp: add exception when message or type is present

Trigger exception creation for any log message with either message or
type. This aligns to otel semconv requirements for exceptions.
  • Loading branch information
endorama authored Nov 20, 2023
1 parent 3d095d3 commit bd8f3ec
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
21 changes: 19 additions & 2 deletions input/otlp/exceptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,36 @@ var (
javaStacktraceMoreRegexp = regexp.MustCompile(`\.\.\. ([0-9]+) more`)
)

const (
emptyExceptionMsg = "[EMPTY]"
)

// convertOpenTelemetryExceptionSpanEvent creates an otel Exception event
// from the specified arguments.
//
// OpenTelemetry semantic convention require the presence of at least one
// of the following attributes:
// - exception.type
// - exception.message
// https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-spans/#attributes
//
// To fulfill this requirement we do not set exception.type if empty but
// we always set exception.message defaulting to a constant value if empty.
func convertOpenTelemetryExceptionSpanEvent(
exceptionType, exceptionMessage, exceptionStacktrace string,
exceptionEscaped bool,
language string,
) *modelpb.Error {
if exceptionMessage == "" {
exceptionMessage = "[EMPTY]"
exceptionMessage = emptyExceptionMsg
}
exceptionHandled := !exceptionEscaped
exceptionError := modelpb.ErrorFromVTPool()
exceptionError.Exception = modelpb.ExceptionFromVTPool()
exceptionError.Exception.Message = exceptionMessage
exceptionError.Exception.Type = exceptionType
if exceptionType != "" {
exceptionError.Exception.Type = exceptionType
}
exceptionError.Exception.Handled = &exceptionHandled
if id, err := newUniqueID(); err == nil {
exceptionError.Id = id
Expand Down
8 changes: 3 additions & 5 deletions input/otlp/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,9 @@ func (c *Consumer) convertLogRecord(
return true
})

if exceptionMessage != "" && exceptionType != "" {
// Per OpenTelemetry semantic conventions:
// `At least one of the following sets of attributes is required:
// - exception.type
// - exception.message`
// NOTE: we consider an error anything that contains an exception type
// or message, indipendently from the severity level.
if exceptionMessage != "" || exceptionType != "" {
event.Error = convertOpenTelemetryExceptionSpanEvent(
exceptionType, exceptionMessage, exceptionStacktrace,
exceptionEscaped, event.Service.Language.Name,
Expand Down

0 comments on commit bd8f3ec

Please sign in to comment.