Add tracer configuration support 55/855/4 v0.0.3
authorRoni Riska <roni.riska@nokia.com>
Fri, 30 Aug 2019 10:36:14 +0000 (13:36 +0300)
committerRoni Riska <roni.riska@nokia.com>
Wed, 4 Sep 2019 07:19:26 +0000 (10:19 +0300)
The tracer configuration is done using environment variables.
By default a no-op tracer is created.

Change-Id: I9c7d0d269c90e0c4588e5b636243f826fc8a4f12
Signed-off-by: Roni Riska <roni.riska@nokia.com>
README.md
go.mod
go.sum
pkg/tracelibgo/tracing.go
pkg/tracelibgo/tracing_test.go

index e11effc..0581318 100644 (file)
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
 
 The library creates a configured tracer instance.
 
-ToDO: configuration...
 
 ## Usage
 
@@ -49,6 +48,23 @@ The serialized span context is got, for example, from the RMR library.
        span := opentracing.GlobalTracer().StartSpan("go test span", opentracing.ChildOf(context))
 ```
 
+## Configuration
+
+The trace library currently supports only [Jaeger](https://www.jaegertracing.io/) [golang client](https://github.com/jaegertracing/jaeger-client-go) tracer implementation.
+The configuration is done using environment variables:
+
+| environment variable         | values                              | default        |
+| ---------------------------- |------------------------------------ | -------------- |
+| TRACING_ENABLED              | 1, true, 0, false                   | false          |
+| TRACING_JAEGER_SAMPLER_TYPE  | const, propabilistic, ratelimiting  | const          |
+| TRACING_JAEGER_SAMPLER_PARAM | float                               | 0.001          |
+| TRACING_JAEGER_AGENT_ADDR    | IP addr[:port]                      | 127.0.0.1:6831 |
+| TRACING_JAEGER_LOG_LEVEL     | all, error, none                    | none           |
+
+Meaning of the configuration variables is described in Jaeger web pages.
+By default a no-op tracer is created.
+
+
 ## Unit testing
 
  GO111MODULE=on go mod download
diff --git a/go.mod b/go.mod
index bfd57df..50ba8e7 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -1,7 +1,9 @@
 module gerrit.o-ran-sc.org/r/ric-plt/tracelibgo
 
 require (
+       github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
        github.com/opentracing/opentracing-go v1.1.0
+       github.com/pkg/errors v0.8.1 // indirect
        github.com/stretchr/testify v1.3.0
        github.com/uber/jaeger-client-go v2.16.0+incompatible
        github.com/uber/jaeger-lib v2.0.0+incompatible // indirect
diff --git a/go.sum b/go.sum
index f30cee3..0c68a67 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,13 @@
+gerrit.o-ran-sc.org/r/com/golog.git v0.0.1 h1:9RfO/Whehaaq5KiJTT7s+YOzmi9mT1C3HktfhwwMEmw=
+gerrit.o-ran-sc.org/r/com/golog.git v0.0.1/go.mod h1:b8YB31U8/4iRpABioeSzGi/YMzOQ/Zq7hrJmmXKqlJk=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 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=
index df2f45c..f0a3ea2 100644 (file)
 package tracelibgo
 
 import (
+       "fmt"
        "io"
+       "os"
+       "strconv"
+       "strings"
 
        "github.com/opentracing/opentracing-go"
-       "github.com/uber/jaeger-client-go"
+       jaegercfg "github.com/uber/jaeger-client-go/config"
+       jaegerlog "github.com/uber/jaeger-client-go/log"
 )
 
+const tracingEnabledEnv string = "TRACING_ENABLED"
+const jaegerSamplerTypeEnv string = "TRACING_JAEGER_SAMPLER_TYPE"
+const jaegerSamplerParamEnv = "TRACING_JAEGER_SAMPLER_PARAM"
+const jaegerAgentAddrEnv = "TRACING_JAEGER_AGENT_ADDR"
+const jaegerLogLevelEnv = "TRACING_JAEGER_LOG_LEVEL"
+
+type confMaker struct {
+       ServiceName string
+}
+
+type logLevel int
+
+const (
+       logAll  logLevel = iota
+       logErr  logLevel = iota
+       logNone logLevel = iota
+)
+
+func (cm *confMaker) GetEnv(envName string, defval string) (retval string) {
+       retval = os.Getenv(envName)
+       if retval == "" {
+               retval = defval
+       }
+       return
+}
+
+func (cm *confMaker) IsTracingEnabled() bool {
+       val := cm.GetEnv(tracingEnabledEnv, "false")
+       if val == "1" || strings.ToLower(val) == "true" {
+               return true
+       }
+       return false
+}
+
+func createDisabledTracer(name string) (opentracing.Tracer, io.Closer) {
+       if name == "" {
+               name = "dummy"
+       }
+       cfg := jaegercfg.Configuration{
+               ServiceName: name,
+               Disabled:    true,
+       }
+       tracer, closer, err := cfg.NewTracer()
+       if err != nil {
+               fmt.Fprintln(os.Stderr, "tracelibgo: trace creation error: ", err.Error())
+       }
+       return tracer, closer
+}
+
+func (cm *confMaker) getSamplerConfig() jaegercfg.SamplerConfig {
+       samplerType := cm.GetEnv(jaegerSamplerTypeEnv, "const")
+       param, err := strconv.ParseFloat(cm.GetEnv(jaegerSamplerParamEnv, "0.001"), 64)
+       if err != nil {
+               param = 0
+       }
+       return jaegercfg.SamplerConfig{Type: samplerType, Param: param}
+}
+
+func (cm *confMaker) getReporterConfig() jaegercfg.ReporterConfig {
+       agentHostPort := cm.GetEnv(jaegerAgentAddrEnv, "127.0.0.1:6831")
+       if !strings.Contains(agentHostPort, ":") {
+               agentHostPort += ":6831"
+       }
+       return jaegercfg.ReporterConfig{LogSpans: cm.getLoggingLevel() == logAll, LocalAgentHostPort: agentHostPort}
+}
+
+func (cm *confMaker) getLoggingLevel() logLevel {
+       level := strings.ToLower(cm.GetEnv(jaegerLogLevelEnv, "error"))
+       switch level {
+       case "error":
+               return logErr
+       case "all":
+               return logAll
+       default:
+               return logNone
+       }
+}
+
 // CreateTracer creates a tracer entry
 func CreateTracer(name string) (opentracing.Tracer, io.Closer) {
-       tracer, closer := jaeger.NewTracer(name,
-               jaeger.NewConstSampler(false),
-               jaeger.NewNullReporter())
+
+       cm := confMaker{name}
+       if !cm.IsTracingEnabled() {
+               return createDisabledTracer(name)
+       }
+       sampler := cm.getSamplerConfig()
+       reporter := cm.getReporterConfig()
+       cfg := jaegercfg.Configuration{
+               ServiceName: name,
+               Disabled:    false,
+               Sampler:     &sampler,
+               Reporter:    &reporter,
+       }
+       var jaegerLoggerOpt jaegercfg.Option
+       switch cm.getLoggingLevel() {
+       case logAll, logErr:
+               jaegerLoggerOpt = jaegercfg.Logger(jaegerlog.StdLogger)
+       default:
+               jaegerLoggerOpt = jaegercfg.Logger(nil)
+       }
+       tracer, closer, err := cfg.NewTracer(jaegerLoggerOpt)
+       if err != nil {
+               fmt.Fprintln(os.Stderr, "tracelibgo: cannot init tracer: "+err.Error())
+               return createDisabledTracer(name)
+       }
        return tracer, closer
 }
index 86a61ce..e5ede67 100644 (file)
 package tracelibgo
 
 import (
+       "os"
        "testing"
+
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/suite"
 )
 
-func TestTracerCreate(t *testing.T) {
+type ConfMakerTestSuite struct {
+       suite.Suite
+       cm confMaker
+}
+
+func (suite *ConfMakerTestSuite) SetupTest() {
+       suite.cm = confMaker{"foo"}
+}
+
+func (suite *ConfMakerTestSuite) TearDownTest() {
+       os.Unsetenv(tracingEnabledEnv)
+       os.Unsetenv(jaegerSamplerTypeEnv)
+       os.Unsetenv(jaegerSamplerParamEnv)
+       os.Unsetenv(jaegerAgentAddrEnv)
+       os.Unsetenv(jaegerLogLevelEnv)
+}
+
+func (suite *ConfMakerTestSuite) TestTracingIsDisabledByDefault() {
+       suite.False(suite.cm.IsTracingEnabled())
+}
+
+func (suite *ConfMakerTestSuite) TestTracingCanBeEnabledWithEnvVar() {
+       os.Setenv(tracingEnabledEnv, "1")
+       suite.True(suite.cm.IsTracingEnabled())
+       os.Setenv(tracingEnabledEnv, "true")
+       suite.True(suite.cm.IsTracingEnabled())
+}
+
+func (suite *ConfMakerTestSuite) TestTracingEnabledWithUnknownValueResultsDisabled() {
+       os.Setenv(tracingEnabledEnv, "0")
+       suite.False(suite.cm.IsTracingEnabled())
+       os.Setenv(tracingEnabledEnv, "foo")
+       suite.False(suite.cm.IsTracingEnabled())
+}
+
+func (suite *ConfMakerTestSuite) TestSamplerTypeDefaultIsConst() {
+       suite.Equal("const", suite.cm.getSamplerConfig().Type)
+}
+
+func (suite *ConfMakerTestSuite) TestSamplerTypeParamDefault() {
+       suite.Equal(0.001, suite.cm.getSamplerConfig().Param)
+}
+
+func (suite *ConfMakerTestSuite) TestSamplerTypeCanBeDefined() {
+       os.Setenv(jaegerSamplerTypeEnv, "probabilistic")
+       suite.Equal("probabilistic", suite.cm.getSamplerConfig().Type)
+}
+
+func (suite *ConfMakerTestSuite) TestIfSamplerParamIsInvalidZeroValueIsUsed() {
+       os.Setenv(jaegerSamplerParamEnv, "foo")
+       suite.Equal(0.0, suite.cm.getSamplerConfig().Param)
+}
+
+func (suite *ConfMakerTestSuite) TestAgentAddrCanBeDefined() {
+       os.Setenv(jaegerAgentAddrEnv, "1.1.1.1:1111")
+       suite.Equal("1.1.1.1:1111", suite.cm.getReporterConfig().LocalAgentHostPort)
+}
+
+func (suite *ConfMakerTestSuite) TestAgentAddressPortIsOptional() {
+       os.Setenv(jaegerAgentAddrEnv, "1.1.1.1")
+       suite.Equal("1.1.1.1:6831", suite.cm.getReporterConfig().LocalAgentHostPort)
+}
+
+func (suite *ConfMakerTestSuite) TestLoggingLevelDefaultIsErr() {
+       suite.Equal(logErr, suite.cm.getLoggingLevel())
+}
+
+func (suite *ConfMakerTestSuite) TestLoggingLevelCanBeConfigured() {
+       os.Setenv(jaegerLogLevelEnv, "error")
+       suite.Equal(logErr, suite.cm.getLoggingLevel())
+       os.Setenv(jaegerLogLevelEnv, "all")
+       suite.Equal(logAll, suite.cm.getLoggingLevel())
+       os.Setenv(jaegerLogLevelEnv, "none")
+       suite.Equal(logNone, suite.cm.getLoggingLevel())
+}
+
+func (suite *ConfMakerTestSuite) TestConfiguredTracerCreate() {
+       os.Setenv(tracingEnabledEnv, "1")
+       os.Setenv(jaegerSamplerParamEnv, "const")
+       os.Setenv(jaegerSamplerParamEnv, "1")
+       os.Setenv(jaegerAgentAddrEnv, "127.0.0.1:6831")
+       tracer, closer := CreateTracer("foo")
+       suite.NotNil(tracer)
+       suite.NotNil(closer)
+}
+
+func (suite *ConfMakerTestSuite) TestIfTracerCreationFailsDisabledTracerIsReturned() {
+       os.Setenv(tracingEnabledEnv, "1")
+       tracer, closer := CreateTracer("") // Empty name is an error
+       suite.NotNil(tracer)
+       suite.NotNil(closer)
+}
+
+func TestConfMakerSuite(t *testing.T) {
+       suite.Run(t, new(ConfMakerTestSuite))
+}
+
+func TestDefaultTracerCreate(t *testing.T) {
        tracer, closer := CreateTracer("foo")
        assert.NotNil(t, tracer)
        assert.NotNil(t, closer)
        err := closer.Close()
        assert.Nil(t, err)
 }
-