processor/sumologicprocessor/log_fields_conversion_processor.go (123 lines of code) (raw):

// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 package sumologicprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/sumologicprocessor" import ( "encoding/hex" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" ) const ( SeverityNumberAttributeName = "loglevel" SeverityTextAttributeName = "severitytext" SpanIDAttributeName = "spanid" TraceIDAttributeName = "traceid" ) type logFieldAttribute struct { Enabled bool `mapstructure:"enabled"` Name string `mapstructure:"name"` } type logFieldAttributesConfig struct { SeverityNumberAttribute *logFieldAttribute `mapstructure:"severity_number"` SeverityTextAttribute *logFieldAttribute `mapstructure:"severity_text"` SpanIDAttribute *logFieldAttribute `mapstructure:"span_id"` TraceIDAttribute *logFieldAttribute `mapstructure:"trace_id"` } // spanIDToHexOrEmptyString returns a hex string from SpanID. // An empty string is returned, if SpanID is empty. func spanIDToHexOrEmptyString(id pcommon.SpanID) string { if id.IsEmpty() { return "" } return hex.EncodeToString(id[:]) } // traceIDToHexOrEmptyString returns a hex string from TraceID. // An empty string is returned, if TraceID is empty. func traceIDToHexOrEmptyString(id pcommon.TraceID) string { if id.IsEmpty() { return "" } return hex.EncodeToString(id[:]) } var severityNumberToLevel = map[string]string{ plog.SeverityNumberUnspecified.String(): "UNSPECIFIED", plog.SeverityNumberTrace.String(): "TRACE", plog.SeverityNumberTrace2.String(): "TRACE2", plog.SeverityNumberTrace3.String(): "TRACE3", plog.SeverityNumberTrace4.String(): "TRACE4", plog.SeverityNumberDebug.String(): "DEBUG", plog.SeverityNumberDebug2.String(): "DEBUG2", plog.SeverityNumberDebug3.String(): "DEBUG3", plog.SeverityNumberDebug4.String(): "DEBUG4", plog.SeverityNumberInfo.String(): "INFO", plog.SeverityNumberInfo2.String(): "INFO2", plog.SeverityNumberInfo3.String(): "INFO3", plog.SeverityNumberInfo4.String(): "INFO4", plog.SeverityNumberWarn.String(): "WARN", plog.SeverityNumberWarn2.String(): "WARN2", plog.SeverityNumberWarn3.String(): "WARN3", plog.SeverityNumberWarn4.String(): "WARN4", plog.SeverityNumberError.String(): "ERROR", plog.SeverityNumberError2.String(): "ERROR2", plog.SeverityNumberError3.String(): "ERROR3", plog.SeverityNumberError4.String(): "ERROR4", plog.SeverityNumberFatal.String(): "FATAL", plog.SeverityNumberFatal2.String(): "FATAL2", plog.SeverityNumberFatal3.String(): "FATAL3", plog.SeverityNumberFatal4.String(): "FATAL4", } // logFieldsConversionProcessor converts specific log entries to attributes which leads to presenting them as fields // in the backend type logFieldsConversionProcessor struct { LogFieldsAttributes *logFieldAttributesConfig } func newLogFieldConversionProcessor(logFieldsAttributes *logFieldAttributesConfig) *logFieldsConversionProcessor { return &logFieldsConversionProcessor{ logFieldsAttributes, } } func (proc *logFieldsConversionProcessor) addAttributes(log plog.LogRecord) { if log.SeverityNumber() != plog.SeverityNumberUnspecified { if _, found := log.Attributes().Get(SeverityNumberAttributeName); !found && proc.LogFieldsAttributes.SeverityNumberAttribute.Enabled { level := severityNumberToLevel[log.SeverityNumber().String()] log.Attributes().PutStr(proc.LogFieldsAttributes.SeverityNumberAttribute.Name, level) } } if _, found := log.Attributes().Get(SeverityTextAttributeName); !found && proc.LogFieldsAttributes.SeverityTextAttribute.Enabled { log.Attributes().PutStr(proc.LogFieldsAttributes.SeverityTextAttribute.Name, log.SeverityText()) } if _, found := log.Attributes().Get(SpanIDAttributeName); !found && proc.LogFieldsAttributes.SpanIDAttribute.Enabled { log.Attributes().PutStr(proc.LogFieldsAttributes.SpanIDAttribute.Name, spanIDToHexOrEmptyString(log.SpanID())) } if _, found := log.Attributes().Get(TraceIDAttributeName); !found && proc.LogFieldsAttributes.TraceIDAttribute.Enabled { log.Attributes().PutStr(proc.LogFieldsAttributes.TraceIDAttribute.Name, traceIDToHexOrEmptyString(log.TraceID())) } } func (proc *logFieldsConversionProcessor) processLogs(logs plog.Logs) error { if !proc.isEnabled() { return nil } rls := logs.ResourceLogs() for i := 0; i < rls.Len(); i++ { ills := rls.At(i).ScopeLogs() for j := 0; j < ills.Len(); j++ { logs := ills.At(j).LogRecords() for k := 0; k < logs.Len(); k++ { proc.addAttributes(logs.At(k)) } } } return nil } func (proc *logFieldsConversionProcessor) processMetrics(_ pmetric.Metrics) error { // No-op. Metrics should not be translated. return nil } func (proc *logFieldsConversionProcessor) processTraces(_ ptrace.Traces) error { // No-op. Traces should not be translated. return nil } func (proc *logFieldsConversionProcessor) isEnabled() bool { return proc.LogFieldsAttributes.SeverityNumberAttribute.Enabled || proc.LogFieldsAttributes.SeverityTextAttribute.Enabled || proc.LogFieldsAttributes.SpanIDAttribute.Enabled || proc.LogFieldsAttributes.TraceIDAttribute.Enabled } func (*logFieldsConversionProcessor) ConfigPropertyName() string { return "field_attributes" }