Skip to content

Commit 07e356a

Browse files
committed
switch to use spanContext object and add unmarshal code
1 parent 4169384 commit 07e356a

File tree

2 files changed

+80
-68
lines changed

2 files changed

+80
-68
lines changed

exporter/exporterhelper/traces.go

+61-59
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package exporterhelper // import "go.opentelemetry.io/collector/exporter/exporte
55

66
import (
77
"context"
8+
"encoding/hex"
89
"encoding/json"
910
"errors"
1011

@@ -46,55 +47,6 @@ func NewTracesQueueBatchSettings() QueueBatchSettings {
4647
}
4748
}
4849

49-
type SerializableLink struct {
50-
TraceID [16]byte `json:"trace_id"`
51-
SpanID [8]byte `json:"span_id"`
52-
TraceFlags byte `json:"trace_flags"`
53-
TraceState trace.TraceState `json:"trace_state"`
54-
}
55-
56-
func (sl *SerializableLink) UnmarshalJSON(data []byte) error {
57-
type Alias SerializableLink // Prevent recursion
58-
aux := &struct {
59-
TraceState string `json:"trace_state"`
60-
*Alias
61-
}{
62-
Alias: (*Alias)(sl),
63-
}
64-
if err := json.Unmarshal(data, &aux); err != nil {
65-
return err
66-
}
67-
if aux.TraceState != "" {
68-
ts, err := trace.ParseTraceState(aux.TraceState)
69-
if err != nil {
70-
return err
71-
}
72-
sl.TraceState = ts
73-
}
74-
return nil
75-
}
76-
77-
func linkToSerializable(l trace.Link) SerializableLink {
78-
return SerializableLink{
79-
TraceID: l.SpanContext.TraceID(),
80-
SpanID: l.SpanContext.SpanID(),
81-
TraceFlags: byte(l.SpanContext.TraceFlags()),
82-
TraceState: l.SpanContext.TraceState(),
83-
}
84-
}
85-
86-
func serializableToLink(sl SerializableLink) trace.Link {
87-
sc := trace.NewSpanContext(trace.SpanContextConfig{
88-
TraceID: sl.TraceID,
89-
SpanID: sl.SpanID,
90-
TraceFlags: trace.TraceFlags(sl.TraceFlags),
91-
TraceState: sl.TraceState,
92-
})
93-
return trace.Link{
94-
SpanContext: sc,
95-
}
96-
}
97-
9850
type tracesRequest struct {
9951
td ptrace.Traces
10052
links []trace.Link
@@ -112,22 +64,72 @@ func newTracesRequest(td ptrace.Traces, links []trace.Link) Request {
11264
type tracesEncoding struct{}
11365

11466
type tracesWithSpanContexts struct {
115-
Traces []byte `json:"traces"`
116-
Links []SerializableLink `json:"links"`
67+
Traces []byte `json:"traces"`
68+
SpanContext []trace.SpanContext `json:"span_context"`
69+
}
70+
71+
// Helper for JSON unmarshaling of SpanContextConfig
72+
73+
type spanContextConfigJSON struct {
74+
TraceID string
75+
SpanID string
76+
TraceFlags string
77+
TraceState string
78+
Remote bool
79+
}
80+
81+
func unmarshalSpanContextConfig(data []byte) (trace.SpanContextConfig, error) {
82+
var aux spanContextConfigJSON
83+
if err := json.Unmarshal(data, &aux); err != nil {
84+
return trace.SpanContextConfig{}, err
85+
}
86+
tid, err := trace.TraceIDFromHex(aux.TraceID)
87+
if err != nil {
88+
return trace.SpanContextConfig{}, err
89+
}
90+
sid, err := trace.SpanIDFromHex(aux.SpanID)
91+
if err != nil {
92+
return trace.SpanContextConfig{}, err
93+
}
94+
ts, err := trace.ParseTraceState(aux.TraceState)
95+
if err != nil {
96+
return trace.SpanContextConfig{}, err
97+
}
98+
tf, err := hex.DecodeString(aux.TraceFlags)
99+
if err != nil {
100+
return trace.SpanContextConfig{}, err
101+
}
102+
if len(tf) != 1 {
103+
return trace.SpanContextConfig{}, errors.New("invalid trace flags")
104+
}
105+
return trace.SpanContextConfig{
106+
TraceID: tid,
107+
SpanID: sid,
108+
TraceFlags: trace.TraceFlags(tf[0]),
109+
TraceState: ts,
110+
Remote: aux.Remote,
111+
}, nil
117112
}
118113

119114
func (tracesEncoding) Unmarshal(bytes []byte) (Request, error) {
120-
var twl tracesWithSpanContexts
115+
var twl struct {
116+
Traces []byte `json:"traces"`
117+
SpanContext []json.RawMessage `json:"span_context"`
118+
}
121119
if err := json.Unmarshal(bytes, &twl); err != nil {
122120
return nil, err
123121
}
124122
traces, err := tracesUnmarshaler.UnmarshalTraces(twl.Traces)
125123
if err != nil {
126124
return nil, err
127125
}
128-
links := make([]trace.Link, len(twl.Links))
129-
for i, sl := range twl.Links {
130-
links[i] = serializableToLink(sl)
126+
links := make([]trace.Link, len(twl.SpanContext))
127+
for i, raw := range twl.SpanContext {
128+
cfg, err := unmarshalSpanContextConfig(raw)
129+
if err != nil {
130+
return nil, err
131+
}
132+
links[i] = trace.Link{SpanContext: trace.NewSpanContext(cfg)}
131133
}
132134
return newTracesRequest(traces, links), nil
133135
}
@@ -138,13 +140,13 @@ func (tracesEncoding) Marshal(req Request) ([]byte, error) {
138140
if err != nil {
139141
return nil, err
140142
}
141-
serializableLinks := make([]SerializableLink, len(tr.links))
143+
spanContexts := make([]trace.SpanContext, len(tr.links))
142144
for i, l := range tr.links {
143-
serializableLinks[i] = linkToSerializable(l)
145+
spanContexts[i] = l.SpanContext
144146
}
145147
twl := tracesWithSpanContexts{
146-
Traces: tracesBytes,
147-
Links: serializableLinks,
148+
Traces: tracesBytes,
149+
SpanContext: spanContexts,
148150
}
149151
return json.Marshal(twl)
150152
}

exporter/exporterhelper/traces_test.go

+19-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package exporterhelper
55

66
import (
77
"context"
8+
"encoding/json"
89
"errors"
910
"testing"
1011
"time"
@@ -480,18 +481,27 @@ func checkWrapSpanForTraces(t *testing.T, sr *tracetest.SpanRecorder, tracer tra
480481

481482
func TestSerializableToLink(t *testing.T) {
482483
ts, err := trace.TraceState{}.Insert("key", "value")
483-
if err != nil {
484-
t.Fatalf("Error inserting trace state: %v", err)
485-
}
486-
sl := SerializableLink{
484+
require.NoError(t, err)
485+
486+
sc := trace.NewSpanContext(trace.SpanContextConfig{
487487
TraceID: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
488488
SpanID: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
489-
TraceFlags: byte(trace.FlagsSampled),
489+
TraceFlags: trace.FlagsSampled,
490490
TraceState: ts,
491-
}
492-
res := serializableToLink(sl)
493-
// TraceState will be empty due to error in inserting Member Key "@key"
494-
assert.Equal(t, ts, res.SpanContext.TraceState())
491+
})
492+
493+
// Marshal and unmarshal SpanContext as JSON
494+
data, err := json.Marshal(sc)
495+
require.NoError(t, err)
496+
497+
sc2, err := unmarshalSpanContextConfig(data)
498+
require.NoError(t, err)
499+
scRestored := trace.NewSpanContext(sc2)
500+
501+
assert.Equal(t, sc.TraceID(), scRestored.TraceID())
502+
assert.Equal(t, sc.SpanID(), scRestored.SpanID())
503+
assert.Equal(t, sc.TraceFlags(), scRestored.TraceFlags())
504+
assert.Equal(t, sc.TraceState(), scRestored.TraceState())
495505
}
496506

497507
func TestTracesEncoding_Unmarshal_InvalidJSON(t *testing.T) {

0 commit comments

Comments
 (0)