Skip to content

Separate model parts into more independent pieces #6581

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

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions model/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2019 The Jaeger Authors.
// Copyright (c) 2017 Uber Technologies, Inc.
// SPDX-License-Identifier: Apache-2.0

package model

const (
// SampledFlag is the bit set in Flags in order to define a span as a sampled span
SampledFlag = Flags(1)
// DebugFlag is the bit set in Flags in order to define a span as a debug span
DebugFlag = Flags(2)
// FirehoseFlag is the bit in Flags in order to define a span as a firehose span
FirehoseFlag = Flags(8)
)

// Flags is a bit map of flags for a span
type Flags uint32

// ------- Flags -------

// SetSampled sets the Flags as sampled
func (f *Flags) SetSampled() {
f.setFlags(SampledFlag)
}

// SetDebug set the Flags as sampled
func (f *Flags) SetDebug() {
f.setFlags(DebugFlag)
}

// SetFirehose set the Flags as firehose enabled
func (f *Flags) SetFirehose() {
f.setFlags(FirehoseFlag)
}

func (f *Flags) setFlags(bit Flags) {
*f |= bit
}

// IsSampled returns true if the Flags denote sampling
func (f Flags) IsSampled() bool {
return f.checkFlags(SampledFlag)
}

// IsDebug returns true if the Flags denote debugging
// Debugging can be useful in testing tracing availability or correctness
func (f Flags) IsDebug() bool {
return f.checkFlags(DebugFlag)
}

// IsFirehoseEnabled returns true if firehose is enabled
// Firehose is used to decide whether to index a span or not
func (f Flags) IsFirehoseEnabled() bool {
return f.checkFlags(FirehoseFlag)
}

func (f Flags) checkFlags(bit Flags) bool {
return f&bit == bit
}
48 changes: 48 additions & 0 deletions model/flags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2019 The Jaeger Authors.
// Copyright (c) 2017 Uber Technologies, Inc.
// SPDX-License-Identifier: Apache-2.0

package model_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/jaegertracing/jaeger/model"
)

func TestIsDebug(t *testing.T) {
flags := model.Flags(0)
flags.SetDebug()
assert.True(t, flags.IsDebug())
flags = model.Flags(0)
assert.False(t, flags.IsDebug())

flags = model.Flags(32)
assert.False(t, flags.IsDebug())
flags.SetDebug()
assert.True(t, flags.IsDebug())
}

func TestIsFirehoseEnabled(t *testing.T) {
flags := model.Flags(0)
assert.False(t, flags.IsFirehoseEnabled())
flags.SetDebug()
flags.SetSampled()
assert.False(t, flags.IsFirehoseEnabled())
flags.SetFirehose()
assert.True(t, flags.IsFirehoseEnabled())

flags = model.Flags(8)
assert.True(t, flags.IsFirehoseEnabled())
}

func TestIsSampled(t *testing.T) {
flags := model.Flags(0)
flags.SetSampled()
assert.True(t, flags.IsSampled())
flags = model.Flags(0)
flags.SetDebug()
assert.False(t, flags.IsSampled())
}
34 changes: 0 additions & 34 deletions model/ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"strconv"

"github.com/gogo/protobuf/jsonpb"
"go.opentelemetry.io/collector/pdata/pcommon"
)

const (
Expand Down Expand Up @@ -146,23 +145,6 @@ func (t *TraceID) UnmarshalJSON(data []byte) error {
return t.Unmarshal(b)
}

// ToOTELTraceID converts the TraceID to OTEL's representation of a trace identitfier.
// This was taken from
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/internal/coreinternal/idutils/big_endian_converter.go.
func (t *TraceID) ToOTELTraceID() pcommon.TraceID {
traceID := [16]byte{}
binary.BigEndian.PutUint64(traceID[:8], t.High)
binary.BigEndian.PutUint64(traceID[8:], t.Low)
return traceID
}

func TraceIDFromOTEL(traceID pcommon.TraceID) TraceID {
return TraceID{
High: binary.BigEndian.Uint64(traceID[:traceIDShortBytesLen]),
Low: binary.BigEndian.Uint64(traceID[traceIDShortBytesLen:]),
}
}

// ------- SpanID -------

// NewSpanID creates a new SpanID from a 64bit unsigned int.
Expand Down Expand Up @@ -261,19 +243,3 @@ func (s *SpanID) UnmarshalJSON(data []byte) error {
func (s *SpanID) UnmarshalJSONPB(_ *jsonpb.Unmarshaler, b []byte) error {
return s.UnmarshalJSON(b)
}

// ToOTELSpanID converts the SpanID to OTEL's representation of a span identitfier.
// This was taken from
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/internal/coreinternal/idutils/big_endian_converter.go.
func (s SpanID) ToOTELSpanID() pcommon.SpanID {
spanID := [8]byte{}
binary.BigEndian.PutUint64(spanID[:], uint64(s))
return pcommon.SpanID(spanID)
}

// ToOTELSpanID converts OTEL's SpanID to the model representation of a span identitfier.
// This was taken from
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/internal/coreinternal/idutils/big_endian_converter.go.
func SpanIDFromOTEL(spanID pcommon.SpanID) SpanID {
return SpanID(binary.BigEndian.Uint64(spanID[:]))
}
77 changes: 77 additions & 0 deletions model/ids_proto_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2019 The Jaeger Authors.
// Copyright (c) 2018 Uber Technologies, Inc.
// SPDX-License-Identifier: Apache-2.0

package model_test

import (
"bytes"
"testing"

"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/jaegertracing/jaeger/model"
"github.com/jaegertracing/jaeger/model/prototest"
)

// TraceID/SpanID fields are defined as bytes in proto, backed by custom types in Go.
// Unfortunately, that means they require manual implementations of proto & json serialization.
// To ensure that it's the same as the default protobuf serialization, file jaeger_test.proto
// contains a copy of SpanRef message without any gogo options. This test file is compiled with
// plain protoc -go_out (without gogo). This test performs proto and JSON marshaling/unmarshaling
// to ensure that the outputs of manual and standard serialization are identical.
func TestTraceSpanIDMarshalProto(t *testing.T) {
testCases := []struct {
name string
marshal func(proto.Message) ([]byte, error)
unmarshal func([]byte, proto.Message) error
expected string
}{
{
name: "protobuf",
marshal: proto.Marshal,
unmarshal: proto.Unmarshal,
},
{
name: "JSON",
marshal: func(m proto.Message) ([]byte, error) {
out := new(bytes.Buffer)
err := new(jsonpb.Marshaler).Marshal(out, m)
if err != nil {
return nil, err
}
return out.Bytes(), nil
},
unmarshal: func(in []byte, m proto.Message) error {
return jsonpb.Unmarshal(bytes.NewReader(in), m)
},
expected: `{"traceId":"AAAAAAAAAAIAAAAAAAAAAw==","spanId":"AAAAAAAAAAs="}`,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
ref1 := model.SpanRef{TraceID: model.NewTraceID(2, 3), SpanID: model.NewSpanID(11)}
ref2 := prototest.SpanRef{
// TODO: would be cool to fuzz that test
TraceId: []byte{0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3},
SpanId: []byte{0, 0, 0, 0, 0, 0, 0, 11},
}
d1, err := testCase.marshal(&ref1)
require.NoError(t, err)
d2, err := testCase.marshal(&ref2)
require.NoError(t, err)
assert.Equal(t, d2, d1)
if testCase.expected != "" {
assert.Equal(t, testCase.expected, string(d1))
}
// test unmarshal
var ref1u model.SpanRef
err = testCase.unmarshal(d2, &ref1u)
require.NoError(t, err)
assert.Equal(t, ref1, ref1u)
})
}
}
135 changes: 0 additions & 135 deletions model/ids_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,14 @@
package model_test

import (
"bytes"
"testing"

"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/pdata/pcommon"

"github.com/jaegertracing/jaeger/model"
"github.com/jaegertracing/jaeger/model/prototest"
)

// TraceID/SpanID fields are defined as bytes in proto, backed by custom types in Go.
// Unfortunately, that means they require manual implementations of proto & json serialization.
// To ensure that it's the same as the default protobuf serialization, file jaeger_test.proto
// contains a copy of SpanRef message without any gogo options. This test file is compiled with
// plain protoc -go_out (without gogo). This test performs proto and JSON marshaling/unmarshaling
// to ensure that the outputs of manual and standard serialization are identical.
func TestTraceSpanIDMarshalProto(t *testing.T) {
testCases := []struct {
name string
marshal func(proto.Message) ([]byte, error)
unmarshal func([]byte, proto.Message) error
expected string
}{
{
name: "protobuf",
marshal: proto.Marshal,
unmarshal: proto.Unmarshal,
},
{
name: "JSON",
marshal: func(m proto.Message) ([]byte, error) {
out := new(bytes.Buffer)
err := new(jsonpb.Marshaler).Marshal(out, m)
if err != nil {
return nil, err
}
return out.Bytes(), nil
},
unmarshal: func(in []byte, m proto.Message) error {
return jsonpb.Unmarshal(bytes.NewReader(in), m)
},
expected: `{"traceId":"AAAAAAAAAAIAAAAAAAAAAw==","spanId":"AAAAAAAAAAs="}`,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
ref1 := model.SpanRef{TraceID: model.NewTraceID(2, 3), SpanID: model.NewSpanID(11)}
ref2 := prototest.SpanRef{
// TODO: would be cool to fuzz that test
TraceId: []byte{0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3},
SpanId: []byte{0, 0, 0, 0, 0, 0, 0, 11},
}
d1, err := testCase.marshal(&ref1)
require.NoError(t, err)
d2, err := testCase.marshal(&ref2)
require.NoError(t, err)
assert.Equal(t, d2, d1)
if testCase.expected != "" {
assert.Equal(t, testCase.expected, string(d1))
}
// test unmarshal
var ref1u model.SpanRef
err = testCase.unmarshal(d2, &ref1u)
require.NoError(t, err)
assert.Equal(t, ref1, ref1u)
})
}
}

func TestSpanIDFromBytes(t *testing.T) {
errTests := [][]byte{
{0, 0, 0, 0},
Expand Down Expand Up @@ -118,74 +54,3 @@ func TestTraceIDFromBytes(t *testing.T) {
assert.Equal(t, test.expected, traceID)
}
}

func TestToOTELTraceID(t *testing.T) {
modelTraceID := model.TraceID{
Low: 3,
High: 2,
}
otelTraceID := modelTraceID.ToOTELTraceID()
expected := []byte{0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3}
require.Equal(t, pcommon.TraceID(expected), otelTraceID)
}

func TestTraceIDFromOTEL(t *testing.T) {
otelTraceID := pcommon.TraceID([]byte{0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3})
expected := model.TraceID{
Low: 3,
High: 2,
}
require.Equal(t, expected, model.TraceIDFromOTEL(otelTraceID))
}

func TestToOTELSpanID(t *testing.T) {
tests := []struct {
name string
spanID model.SpanID
expected pcommon.SpanID
}{
{
name: "zero span ID",
spanID: model.NewSpanID(0),
expected: pcommon.NewSpanIDEmpty(),
},
{
name: "non-zero span ID",
spanID: model.NewSpanID(1),
expected: pcommon.SpanID([8]byte{0, 0, 0, 0, 0, 0, 0, 1}),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := test.spanID.ToOTELSpanID()
assert.Equal(t, test.expected, actual)
})
}
}

func TestSpanIDFromOTEL(t *testing.T) {
tests := []struct {
name string
otelSpanID pcommon.SpanID
expected model.SpanID
}{
{
name: "zero span ID",
otelSpanID: pcommon.NewSpanIDEmpty(),
expected: model.NewSpanID(0),
},
{
name: "non-zero span ID",
otelSpanID: pcommon.SpanID([8]byte{0, 0, 0, 0, 0, 0, 0, 1}),
expected: model.NewSpanID(1),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := model.SpanIDFromOTEL(test.otelSpanID)
assert.Equal(t, test.expected, actual)
})
}
}
Loading
Loading