// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 package stdoutlog // import "go.opentelemetry.io/otel/exporters/stdout/stdoutlog" import ( "encoding/json" "errors" "time" "go.opentelemetry.io/otel/log" "go.opentelemetry.io/otel/sdk/instrumentation" sdklog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/trace" ) func newValue(v log.Value) value { return value{Value: v} } type value struct { log.Value } // MarshalJSON implements a custom marshal function to encode log.Value. func (v value) MarshalJSON() ([]byte, error) { var jsonVal struct { Type string Value any } jsonVal.Type = v.Kind().String() switch v.Kind() { case log.KindString: jsonVal.Value = v.AsString() case log.KindInt64: jsonVal.Value = v.AsInt64() case log.KindFloat64: jsonVal.Value = v.AsFloat64() case log.KindBool: jsonVal.Value = v.AsBool() case log.KindBytes: jsonVal.Value = v.AsBytes() case log.KindMap: m := v.AsMap() values := make([]keyValue, 0, len(m)) for _, kv := range m { values = append(values, keyValue{ Key: kv.Key, Value: newValue(kv.Value), }) } jsonVal.Value = values case log.KindSlice: s := v.AsSlice() values := make([]value, 0, len(s)) for _, e := range s { values = append(values, newValue(e)) } jsonVal.Value = values case log.KindEmpty: jsonVal.Value = nil default: return nil, errors.New("invalid Kind") } return json.Marshal(jsonVal) } type keyValue struct { Key string Value value } // recordJSON is a JSON-serializable representation of a Record. type recordJSON struct { Timestamp *time.Time `json:",omitempty"` ObservedTimestamp *time.Time `json:",omitempty"` EventName string `json:",omitempty"` Severity log.Severity SeverityText string Body value Attributes []keyValue TraceID trace.TraceID SpanID trace.SpanID TraceFlags trace.TraceFlags Resource *resource.Resource Scope instrumentation.Scope DroppedAttributes int } func (e *Exporter) newRecordJSON(r sdklog.Record) recordJSON { res := r.Resource() newRecord := recordJSON{ EventName: r.EventName(), Severity: r.Severity(), SeverityText: r.SeverityText(), Body: newValue(r.Body()), TraceID: r.TraceID(), SpanID: r.SpanID(), TraceFlags: r.TraceFlags(), Attributes: make([]keyValue, 0, r.AttributesLen()), Resource: res, Scope: r.InstrumentationScope(), DroppedAttributes: r.DroppedAttributes(), } r.WalkAttributes(func(kv log.KeyValue) bool { newRecord.Attributes = append(newRecord.Attributes, keyValue{ Key: kv.Key, Value: newValue(kv.Value), }) return true }) if e.timestamps { timestamp := r.Timestamp() newRecord.Timestamp = ×tamp observedTimestamp := r.ObservedTimestamp() newRecord.ObservedTimestamp = &observedTimestamp } return newRecord }