mirror of https://github.com/knative/pkg.git
ConfigOptions return an error (#657)
* ConfigOptions return an error, so we can react to things failing, rather than only reading it in the logs. * Add unit tests. * PR comments. * PR comment - remove TODO.
This commit is contained in:
parent
121082452b
commit
6074a277ac
|
|
@ -2,12 +2,14 @@ package tracing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"contrib.go.opencensus.io/exporter/stackdriver"
|
"contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
oczipkin "contrib.go.opencensus.io/exporter/zipkin"
|
oczipkin "contrib.go.opencensus.io/exporter/zipkin"
|
||||||
zipkin "github.com/openzipkin/zipkin-go"
|
"github.com/openzipkin/zipkin-go"
|
||||||
httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
|
httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
@ -16,7 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigOption is the interface for adding additional exporters and configuring opencensus tracing.
|
// ConfigOption is the interface for adding additional exporters and configuring opencensus tracing.
|
||||||
type ConfigOption func(*config.Config)
|
type ConfigOption func(*config.Config) error
|
||||||
|
|
||||||
// OpenCensusTracer is responsible for managing and updating configuration of OpenCensus tracing
|
// OpenCensusTracer is responsible for managing and updating configuration of OpenCensus tracing
|
||||||
type OpenCensusTracer struct {
|
type OpenCensusTracer struct {
|
||||||
|
|
@ -46,14 +48,16 @@ func (oct *OpenCensusTracer) ApplyConfig(cfg *config.Config) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short circuit if our config hasnt changed
|
// Short circuit if our config hasn't changed.
|
||||||
if oct.curCfg != nil && oct.curCfg.Equals(cfg) {
|
if oct.curCfg != nil && oct.curCfg.Equals(cfg) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply config options
|
// Apply config options
|
||||||
for _, configOpt := range oct.configOptions {
|
for _, configOpt := range oct.configOptions {
|
||||||
configOpt(cfg)
|
if err = configOpt(cfg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
|
|
@ -70,7 +74,9 @@ func (oct *OpenCensusTracer) Finish() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, configOpt := range oct.configOptions {
|
for _, configOpt := range oct.configOptions {
|
||||||
configOpt(nil)
|
if err = configOpt(nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
globalOct = nil
|
globalOct = nil
|
||||||
|
|
||||||
|
|
@ -108,7 +114,7 @@ func createOCTConfig(cfg *config.Config) *trace.Config {
|
||||||
// WithExporter returns a ConfigOption for use with NewOpenCensusTracer that configures
|
// WithExporter returns a ConfigOption for use with NewOpenCensusTracer that configures
|
||||||
// it to export traces based on the configuration read from config-tracing.
|
// it to export traces based on the configuration read from config-tracing.
|
||||||
func WithExporter(name string, logger *zap.SugaredLogger) ConfigOption {
|
func WithExporter(name string, logger *zap.SugaredLogger) ConfigOption {
|
||||||
return func(cfg *config.Config) {
|
return func(cfg *config.Config) error {
|
||||||
var (
|
var (
|
||||||
exporter trace.Exporter
|
exporter trace.Exporter
|
||||||
closer io.Closer
|
closer io.Closer
|
||||||
|
|
@ -120,15 +126,25 @@ func WithExporter(name string, logger *zap.SugaredLogger) ConfigOption {
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorw("error reading project-id from metadata", zap.Error(err))
|
logger.Errorw("error reading project-id from metadata", zap.Error(err))
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
exporter = exp
|
exporter = exp
|
||||||
case config.Zipkin:
|
case config.Zipkin:
|
||||||
|
// If name isn't specified, then zipkin.NewEndpoint will return an error saying that it
|
||||||
|
// can't find the host named ''. So, if not specified, default it to this machine's
|
||||||
|
// hostname.
|
||||||
|
if name == "" {
|
||||||
|
n, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get hostname: %v", err)
|
||||||
|
}
|
||||||
|
name = n
|
||||||
|
}
|
||||||
hostPort := name + ":80"
|
hostPort := name + ":80"
|
||||||
zipEP, err := zipkin.NewEndpoint(name, hostPort)
|
zipEP, err := zipkin.NewEndpoint(name, hostPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorw("error building zipkin endpoint", zap.Error(err))
|
logger.Errorw("error building zipkin endpoint", zap.Error(err))
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
reporter := httpreporter.NewReporter(cfg.ZipkinEndpoint)
|
reporter := httpreporter.NewReporter(cfg.ZipkinEndpoint)
|
||||||
exporter = oczipkin.NewExporter(reporter, zipEP)
|
exporter = oczipkin.NewExporter(reporter, zipEP)
|
||||||
|
|
@ -149,5 +165,7 @@ func WithExporter(name string, logger *zap.SugaredLogger) ConfigOption {
|
||||||
|
|
||||||
globalOct.exporter = exporter
|
globalOct.exporter = exporter
|
||||||
globalOct.closer = closer
|
globalOct.closer = closer
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package tracing_test
|
package tracing_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "knative.dev/pkg/tracing"
|
. "knative.dev/pkg/tracing"
|
||||||
|
|
@ -47,3 +48,43 @@ func TestOpenCensusTracerGlobalLifecycle(t *testing.T) {
|
||||||
}
|
}
|
||||||
otherOCT.Finish()
|
otherOCT.Finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOpenCensusTraceApplyConfigFailingConfigOption(t *testing.T) {
|
||||||
|
coErr := errors.New("configOption error")
|
||||||
|
oct := NewOpenCensusTracer(func(c *config.Config) error {
|
||||||
|
if c != nil {
|
||||||
|
return coErr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err := oct.ApplyConfig(&config.Config{}); err != coErr {
|
||||||
|
t.Errorf("Expected error not seen. Got %q. Want %q", err, coErr)
|
||||||
|
}
|
||||||
|
if err := oct.Finish(); err != nil {
|
||||||
|
t.Errorf("Unexpected error Finishing: %q", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpenCensusTraceFinishFailingConfigOption(t *testing.T) {
|
||||||
|
coErr := errors.New("configOption error")
|
||||||
|
errToReturn := coErr
|
||||||
|
oct := NewOpenCensusTracer(func(c *config.Config) error {
|
||||||
|
if c == nil {
|
||||||
|
// We need finish to work on the second try, otherwise we have mutated global state. So,
|
||||||
|
// make sure that next run through, the returned error is nil.
|
||||||
|
e := errToReturn
|
||||||
|
errToReturn = nil
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err := oct.ApplyConfig(&config.Config{}); err != nil {
|
||||||
|
t.Errorf("Unexpected error Applying Config: %q", err)
|
||||||
|
}
|
||||||
|
if err := oct.Finish(); err != coErr {
|
||||||
|
t.Errorf("Expected error not seen. Got %q. Want %q", err, coErr)
|
||||||
|
}
|
||||||
|
if err := oct.Finish(); err != nil {
|
||||||
|
t.Errorf("Unexpected error on second Finish (global state mutated, other tests may fail oddly): %q", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ type ZipkinReporterFactory func(*config.Config) (zipkinreporter.Reporter, error)
|
||||||
// - WithExporter() in production code
|
// - WithExporter() in production code
|
||||||
// - testing/FakeZipkinExporter() in test code.
|
// - testing/FakeZipkinExporter() in test code.
|
||||||
func WithZipkinExporter(reporterFact ZipkinReporterFactory, endpoint *zipkinmodel.Endpoint) ConfigOption {
|
func WithZipkinExporter(reporterFact ZipkinReporterFactory, endpoint *zipkinmodel.Endpoint) ConfigOption {
|
||||||
return func(cfg *config.Config) {
|
return func(cfg *config.Config) error {
|
||||||
var (
|
var (
|
||||||
reporter zipkinreporter.Reporter
|
reporter zipkinreporter.Reporter
|
||||||
exporter trace.Exporter
|
exporter trace.Exporter
|
||||||
|
|
@ -43,8 +43,7 @@ func WithZipkinExporter(reporterFact ZipkinReporterFactory, endpoint *zipkinmode
|
||||||
// do this before cleanup to minimize time where we have duplicate exporters
|
// do this before cleanup to minimize time where we have duplicate exporters
|
||||||
reporter, err := reporterFact(cfg)
|
reporter, err := reporterFact(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(greghaynes) log this error
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
exporter := zipkin.NewExporter(reporter, endpoint)
|
exporter := zipkin.NewExporter(reporter, endpoint)
|
||||||
trace.RegisterExporter(exporter)
|
trace.RegisterExporter(exporter)
|
||||||
|
|
@ -63,5 +62,7 @@ func WithZipkinExporter(reporterFact ZipkinReporterFactory, endpoint *zipkinmode
|
||||||
|
|
||||||
oct.closer = reporter
|
oct.closer = reporter
|
||||||
oct.exporter = exporter
|
oct.exporter = exporter
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue