Skip to content

Commit

Permalink
init (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyamor authored Nov 23, 2023
1 parent 4dddf43 commit 003b78f
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/.idea/
1 change: 0 additions & 1 deletion CODEOWNERS

This file was deleted.

20 changes: 20 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module com.coralogix.opentelemetry-go

go 1.17

require (
github.com/stretchr/testify v1.8.1
go.opentelemetry.io/otel v1.11.2
go.opentelemetry.io/otel/sdk v1.11.2
go.opentelemetry.io/otel/trace v1.11.2

)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
32 changes: 32 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0=
go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI=
go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU=
go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU=
go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0=
go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
87 changes: 87 additions & 0 deletions sampler/coralogix-sampler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package sampler

import (
"context"
"go.opentelemetry.io/otel/attribute"
traceSdk "go.opentelemetry.io/otel/sdk/trace"
traceCore "go.opentelemetry.io/otel/trace"
)

const (
TransactionIdentifier = "cgx.transaction"
TransactionIdentifierTraceState = "cgx_transaction"
DistributedTransactionIdentifier = "cgx.transaction.distributed"
DistributedTransactionIdentifierTraceState = "cgx_transaction_distributed"
)

type CoralogixSampler struct {
adaptedSampler traceSdk.Sampler
}

func NewCoralogixSampler(adaptedSampler traceSdk.Sampler) *CoralogixSampler {
if adaptedSampler == nil {
panic("sampler is null")
}
return &CoralogixSampler{
adaptedSampler: adaptedSampler,
}
}

func (s *CoralogixSampler) ShouldSample(parameters traceSdk.SamplingParameters) traceSdk.SamplingResult {
adaptedSamplingResult := s.adaptedSampler.ShouldSample(parameters)

return s.generateTransactionSamplingResult(parameters.ParentContext, parameters.Name, adaptedSamplingResult)
}

func (s *CoralogixSampler) generateTransactionSamplingResult(ctx context.Context, name string, adaptedSamplingResult traceSdk.SamplingResult) traceSdk.SamplingResult {
newTracingState := s.generateNewTraceState(ctx, name, adaptedSamplingResult)
newAttributes := s.injectAttributes(adaptedSamplingResult, newTracingState)
return traceSdk.SamplingResult{
Decision: adaptedSamplingResult.Decision,
Attributes: newAttributes,
Tracestate: newTracingState,
}
}

func (s *CoralogixSampler) injectAttributes(adaptedSamplingResult traceSdk.SamplingResult, newTracingState traceCore.TraceState) []attribute.KeyValue {
sampledAttributes := adaptedSamplingResult.Attributes

transactionIdentifier := attribute.String(TransactionIdentifier, newTracingState.Get(TransactionIdentifierTraceState))
distributedTransactionIdentifier := attribute.String(DistributedTransactionIdentifier, newTracingState.Get(DistributedTransactionIdentifierTraceState))

return append(sampledAttributes, transactionIdentifier, distributedTransactionIdentifier)
}

func (s *CoralogixSampler) getDescription() string {
return "coralogix-sampler"
}

func (s *CoralogixSampler) generateNewTraceState(ctx context.Context, name string, samplingResult traceSdk.SamplingResult) traceCore.TraceState {
parentSpanContext := s.getParentSpanContext(ctx)
parentTraceState := samplingResult.Tracestate

if !parentSpanContext.IsRemote() && parentTraceState.Get(TransactionIdentifierTraceState) != "" {
return parentTraceState
}

parentTraceState, err := parentTraceState.Insert(TransactionIdentifierTraceState, name)
if err != nil {
return parentTraceState
}
if parentTraceState.Get(DistributedTransactionIdentifierTraceState) == "" {
parentTraceState, err = parentTraceState.Insert(DistributedTransactionIdentifierTraceState, name)
if err != nil {
return parentTraceState
}
}

return parentTraceState
}

func (s *CoralogixSampler) getParentSpanContext(ctx context.Context) traceCore.SpanContext {
span := traceCore.SpanFromContext(ctx)
if span != nil {
return span.SpanContext()
}
return traceCore.SpanContext{}
}
194 changes: 194 additions & 0 deletions sampler/coralogix-sampler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package sampler

import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/attribute"
traceSdk "go.opentelemetry.io/otel/sdk/trace"
"testing"
)

import (
"context"
traceCore "go.opentelemetry.io/otel/trace"
)

const (
spanName = "spanName"
)

func TestCoralogixSampler_ShouldSample(t *testing.T) {
t.Run("When_alwaysSampler_Should_AppendAttributesAndState", func(t *testing.T) {
alwaysSampler := traceSdk.AlwaysSample()
coralogixSampler := NewCoralogixSampler(alwaysSampler)

// Act
parameters := traceSdk.SamplingParameters{
ParentContext: context.Background(),
Name: spanName,
Attributes: []attribute.KeyValue{},
}
result := coralogixSampler.ShouldSample(parameters)

expectedAttributes := []attribute.KeyValue{
attribute.String(TransactionIdentifier, spanName),
attribute.String(DistributedTransactionIdentifier, spanName),
}

expectedTraceState := traceCore.TraceState{}

expectedTraceState, _ = expectedTraceState.Insert(TransactionIdentifierTraceState, spanName)
expectedTraceState, _ = expectedTraceState.Insert(DistributedTransactionIdentifierTraceState, spanName)

assert.Equal(t, traceSdk.RecordAndSample, result.Decision)
assert.ElementsMatch(t, expectedAttributes, result.Attributes)
assert.Equal(t, expectedTraceState, result.Tracestate)
})

t.Run("When_NeverSample_Should_AppendAttributesAndState", func(t *testing.T) {
neverSampler := traceSdk.NeverSample()
coralogixSampler := NewCoralogixSampler(neverSampler)

// Act
parameters := traceSdk.SamplingParameters{
ParentContext: context.Background(),
Name: spanName,
Attributes: []attribute.KeyValue{},
}
result := coralogixSampler.ShouldSample(parameters)

expectedAttributes := []attribute.KeyValue{
attribute.String(TransactionIdentifier, spanName),
attribute.String(DistributedTransactionIdentifier, spanName),
}

expectedTraceState := traceCore.TraceState{}

expectedTraceState, _ = expectedTraceState.Insert(TransactionIdentifierTraceState, spanName)
expectedTraceState, _ = expectedTraceState.Insert(DistributedTransactionIdentifierTraceState, spanName)

assert.Equal(t, traceSdk.Drop, result.Decision)
assert.ElementsMatch(t, expectedAttributes, result.Attributes)
assert.Equal(t, expectedTraceState, result.Tracestate)
})

t.Run("When_CustomSamplerIsNull_ShouldFailInit", func(t *testing.T) {
assert.Panics(t, func() {
_ = NewCoralogixSampler(nil)
})
})

t.Run("When_ParentContextExistsAndNotRemote_ShouldCopyParentTraceState", func(t *testing.T) {
alwaysSampler := traceSdk.AlwaysSample()
coralogixSampler := NewCoralogixSampler(alwaysSampler)

traceState := traceCore.TraceState{}

traceState, _ = traceState.Insert(TransactionIdentifierTraceState, "fatherSpanName")
traceState, _ = traceState.Insert(DistributedTransactionIdentifierTraceState, "fatherSpanName")

parentSpan := traceCore.NewSpanContext(traceCore.SpanContextConfig{
TraceID: traceCore.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: traceCore.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
TraceFlags: traceCore.FlagsSampled,
TraceState: traceState,
Remote: false,
})
parentCtx := traceCore.ContextWithSpanContext(context.Background(), parentSpan)

// Act
parameters := traceSdk.SamplingParameters{
ParentContext: parentCtx,
Name: spanName,
Attributes: []attribute.KeyValue{},
}
result := coralogixSampler.ShouldSample(parameters)

expectedAttributes := []attribute.KeyValue{
attribute.String(TransactionIdentifier, "fatherSpanName"),
attribute.String(DistributedTransactionIdentifier, "fatherSpanName"),
}
expectedTraceState := traceCore.TraceState{}
expectedTraceState, _ = traceState.Insert(TransactionIdentifierTraceState, "fatherSpanName")
expectedTraceState, _ = traceState.Insert(DistributedTransactionIdentifierTraceState, "fatherSpanName")

assert.ElementsMatch(t, expectedAttributes, result.Attributes)
assert.Equal(t, expectedTraceState, result.Tracestate)
})
t.Run("When_ParentContextExistsAndRemote_ShouldCopyParentTraceState", func(t *testing.T) {
alwaysSampler := traceSdk.AlwaysSample()
coralogixSampler := NewCoralogixSampler(alwaysSampler)

traceState := traceCore.TraceState{}

traceState, _ = traceState.Insert(TransactionIdentifierTraceState, "fatherSpanName")
traceState, _ = traceState.Insert(DistributedTransactionIdentifierTraceState, "fatherSpanName")

parentSpan := traceCore.NewSpanContext(traceCore.SpanContextConfig{
TraceID: traceCore.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: traceCore.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
TraceFlags: traceCore.FlagsSampled,
TraceState: traceState,
Remote: true,
})
parentCtx := traceCore.ContextWithSpanContext(context.Background(), parentSpan)

// Act
parameters := traceSdk.SamplingParameters{
ParentContext: parentCtx,
Name: spanName,
Attributes: []attribute.KeyValue{},
}
result := coralogixSampler.ShouldSample(parameters)

expectedAttributes := []attribute.KeyValue{
attribute.String(TransactionIdentifier, "spanName"),
attribute.String(DistributedTransactionIdentifier, "fatherSpanName"),
}
expectedTraceState := traceCore.TraceState{}
expectedTraceState, _ = expectedTraceState.Insert(TransactionIdentifierTraceState, spanName)
expectedTraceState, _ = expectedTraceState.Insert(DistributedTransactionIdentifierTraceState, "fatherSpanName")

assert.ElementsMatch(t, expectedAttributes, result.Attributes)
assert.Equal(t, expectedTraceState.Get(TransactionIdentifierTraceState), result.Tracestate.Get(TransactionIdentifierTraceState))
assert.Equal(t, expectedTraceState.Get(DistributedTransactionIdentifierTraceState), result.Tracestate.Get(DistributedTransactionIdentifierTraceState))
})

t.Run("When_ParentContextExistsAndRemote_ShouldCopyParentTraceState", func(t *testing.T) {
alwaysSampler := traceSdk.AlwaysSample()
coralogixSampler := NewCoralogixSampler(alwaysSampler)

traceState := traceCore.TraceState{}

traceState, _ = traceState.Insert(TransactionIdentifierTraceState, "fatherSpanName")
traceState, _ = traceState.Insert(DistributedTransactionIdentifierTraceState, "fatherSpanName")

parentSpan := traceCore.NewSpanContext(traceCore.SpanContextConfig{
TraceID: traceCore.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
SpanID: traceCore.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8},
TraceFlags: traceCore.FlagsSampled,
TraceState: traceState,
Remote: true,
})
parentCtx := traceCore.ContextWithSpanContext(context.Background(), parentSpan)

// Act
parameters := traceSdk.SamplingParameters{
ParentContext: parentCtx,
Name: spanName,
Attributes: []attribute.KeyValue{},
}
result := coralogixSampler.ShouldSample(parameters)

expectedAttributes := []attribute.KeyValue{
attribute.String(TransactionIdentifier, "spanName"),
attribute.String(DistributedTransactionIdentifier, "fatherSpanName"),
}
expectedTraceState := traceCore.TraceState{}
expectedTraceState, _ = expectedTraceState.Insert(TransactionIdentifierTraceState, spanName)
expectedTraceState, _ = expectedTraceState.Insert(DistributedTransactionIdentifierTraceState, "fatherSpanName")

assert.ElementsMatch(t, expectedAttributes, result.Attributes)
assert.Equal(t, expectedTraceState.Get(TransactionIdentifierTraceState), result.Tracestate.Get(TransactionIdentifierTraceState))
assert.Equal(t, expectedTraceState.Get(DistributedTransactionIdentifierTraceState), result.Tracestate.Get(DistributedTransactionIdentifierTraceState))
})
}

0 comments on commit 003b78f

Please sign in to comment.