Skip to content

Commit 6178903

Browse files
yurishkurohanyuancheungMrAlias
authored
[samplers/jaegerremote] Change parser to support enums as both strings and numbers (#3183)
* squash * delint * undo .gitignore * Move changelog entry to unreleased --------- Co-authored-by: Chester Cheung <[email protected]> Co-authored-by: Tyler Yahn <[email protected]>
1 parent 0a2a048 commit 6178903

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1212

1313
- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068)
1414

15+
### Changed
16+
17+
- `samplers/jaegerremote`: change to use protobuf parser instead of encoding/json to accept enums as strings. (#3183)
18+
1519
## [1.14.0/0.39.0/0.8.0] - 2023-02-07
1620

1721
### Changed
1822

1923
- Change `runtime.uptime` instrument in `go.opentelemetry.io/contrib/instrumentation/runtime` from `Int64ObservableUpDownCounter` to `Int64ObservableCounter`,
2024
since the value is monotonic. (#3347)
25+
- `samplers/jaegerremote`: change to use protobuf parser instead of encoding/json to accept enums as strings. (#3183)
2126

2227
### Fixed
2328

samplers/jaegerremote/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Jaeger Remote Sampler
22

3-
This package implements [Jaeger remote sampler](https://www.jaegertracing.io/docs/latest/sampling/#collector-sampling-configuration).
3+
This package implements [Jaeger remote sampler](https://www.jaegertracing.io/docs/latest/sampling/#remote-sampling).
44
Remote sampler allows defining sampling configuration for services at the backend, at the granularity of service + endpoint.
55
When using the Jaeger backend, the sampling configuration can come from two sources:
66

samplers/jaegerremote/sampler_remote.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package jaegerremote // import "go.opentelemetry.io/contrib/samplers/jaegerremote"
1818

1919
import (
20-
"encoding/json"
20+
"bytes"
2121
"fmt"
2222
"io"
2323
"net/http"
@@ -26,6 +26,8 @@ import (
2626
"sync/atomic"
2727
"time"
2828

29+
"github.com/gogo/protobuf/jsonpb"
30+
2931
jaeger_api_v2 "go.opentelemetry.io/contrib/samplers/jaegerremote/internal/proto-gen/jaeger-idl/proto/api_v2"
3032
"go.opentelemetry.io/otel/sdk/trace"
3133
)
@@ -311,7 +313,11 @@ type samplingStrategyParserImpl struct{}
311313

312314
func (p *samplingStrategyParserImpl) Parse(response []byte) (interface{}, error) {
313315
strategy := new(jaeger_api_v2.SamplingStrategyResponse)
314-
if err := json.Unmarshal(response, strategy); err != nil {
316+
// Official Jaeger Remote Sampling protocol contains enums encoded as strings.
317+
// Legacy protocol contains enums as numbers.
318+
// Gogo's jsonpb module can parse either format.
319+
// Cf. https://github.com/open-telemetry/opentelemetry-go-contrib/issues/3184
320+
if err := jsonpb.Unmarshal(bytes.NewReader(response), strategy); err != nil {
315321
return nil, err
316322
}
317323
return strategy, nil

samplers/jaegerremote/sampler_remote_test.go

+52
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,55 @@ func getSamplingStrategyResponse(strategyType jaeger_api_v2.SamplingStrategyType
535535
}
536536
return nil
537537
}
538+
539+
func TestSamplingStrategyParserImpl(t *testing.T) {
540+
assertProbabilistic := func(t *testing.T, s *jaeger_api_v2.SamplingStrategyResponse) {
541+
require.NotNil(t, s.GetProbabilisticSampling(), "output: %+v", s)
542+
require.EqualValues(t, 0.42, s.GetProbabilisticSampling().GetSamplingRate(), "output: %+v", s)
543+
}
544+
assertRateLimiting := func(t *testing.T, s *jaeger_api_v2.SamplingStrategyResponse) {
545+
require.NotNil(t, s.GetRateLimitingSampling(), "output: %+v", s)
546+
require.EqualValues(t, 42, s.GetRateLimitingSampling().GetMaxTracesPerSecond(), "output: %+v", s)
547+
}
548+
tests := []struct {
549+
name string
550+
json string
551+
assert func(t *testing.T, s *jaeger_api_v2.SamplingStrategyResponse)
552+
}{
553+
{
554+
name: "official JSON probabilistic",
555+
json: `{"strategyType":"PROBABILISTIC","probabilisticSampling":{"samplingRate":0.42}}`,
556+
assert: assertProbabilistic,
557+
},
558+
{
559+
name: "official JSON rate limiting",
560+
json: `{"strategyType":"RATE_LIMITING","rateLimitingSampling":{"maxTracesPerSecond":42}}`,
561+
assert: assertRateLimiting,
562+
},
563+
{
564+
name: "legacy JSON probabilistic",
565+
json: `{"strategyType":0,"probabilisticSampling":{"samplingRate":0.42}}`,
566+
assert: assertProbabilistic,
567+
},
568+
{
569+
name: "legacy JSON rate limiting",
570+
json: `{"strategyType":1,"rateLimitingSampling":{"maxTracesPerSecond":42}}`,
571+
assert: assertRateLimiting,
572+
},
573+
}
574+
for _, test := range tests {
575+
t.Run(test.name, func(t *testing.T) {
576+
val, err := new(samplingStrategyParserImpl).Parse([]byte(test.json))
577+
require.NoError(t, err)
578+
s := val.(*jaeger_api_v2.SamplingStrategyResponse)
579+
test.assert(t, s)
580+
})
581+
}
582+
}
583+
584+
func TestSamplingStrategyParserImpl_Error(t *testing.T) {
585+
json := `{"strategyType":"foo_bar","probabilisticSampling":{"samplingRate":0.42}}`
586+
val, err := new(samplingStrategyParserImpl).Parse([]byte(json))
587+
require.Error(t, err, "output: %+v", val)
588+
require.Contains(t, err.Error(), `unknown value "foo_bar"`)
589+
}

0 commit comments

Comments
 (0)