From ef402883c3ac3e5bf3c52eecf887849cc9b14190 Mon Sep 17 00:00:00 2001 From: Ullaakut Date: Mon, 2 Oct 2023 12:33:59 +0200 Subject: [PATCH 1/2] feat: add observer package --- README.md | 48 ++++++++++++++++++++++++++++++++++++++ observe/observer.go | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 observe/observer.go diff --git a/README.md b/README.md index 81ba828..6d876ed 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ func yourAction(c *cli.Context) error { // Run your application here... } ``` + ## Flags ### Logger @@ -154,3 +155,50 @@ Example: `--tracing.endpoint="agent-host:port"` or `--tracing.endpoint="http://h This flag sets the sample ratio of spans that will be reported to the exporter. This should be between 0 and 1. Example: `--tracing.ratio=0.2` + +### Observer + +The observe package exposes an `Observer` type which is essentially a helper that combines a logger, tracer and statter. +It is useful if you use all three for your services and want to avoid carrying around many arguments. + +Here is an example of how one might use it: + +```go +func runServer(c *cli.Context) error { + ctx, cancel := context.WithCancel(c.Context) + defer cancel() + + obsvr, err := cmd.New(c, svcName, version) + if err != nil { + return err + } + defer obsvr.Close() + + // Initialize components by passing the obsvr variable. + return nil +} + +func New(c *cli.Context, svc, version string) (*observe.Observer, error) { + log, logCancel, err := NewLogger(c, svc) + if err != nil { + return nil, err + } + + stats, statsCancel, err := NewStatter(c, log, svc) + if err != nil { + logCancel() + return nil, err + } + + tracer, traceCancel, err := NewTracer(c, log, svc, version) + if err != nil { + logCancel() + statsCancel() + return nil, err + } + + return observe.New(log, stats, tracer, traceCancel, statsCancel, logCancel), nil +} +``` + +It also exposes `NewFake` which allows you to pass fake loggers, tracers and statters in your tests easily. diff --git a/observe/observer.go b/observe/observer.go new file mode 100644 index 0000000..155d34c --- /dev/null +++ b/observe/observer.go @@ -0,0 +1,56 @@ +package observe + +import ( + "io" + "time" + + "github.com/hamba/logger/v2" + "github.com/hamba/statter/v2" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/trace" +) + +// Observer contains observability primitives. +type Observer struct { + Log *logger.Logger + Stats *statter.Statter + TraceProv trace.TracerProvider + + closeFns []func() +} + +// New returns an observer with the given observability primitives. +func New(log *logger.Logger, stats *statter.Statter, traceProv trace.TracerProvider, closeFns ...func()) *Observer { + return &Observer{ + Log: log, + Stats: stats, + TraceProv: traceProv, + closeFns: closeFns, + } +} + +// Tracer returns a tracer with the given name and options. +// If no trace provider has been set, this function will panic. +func (o *Observer) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + if o.TraceProv == nil { + panic("calling tracer when no trace provider has been set") + } + return o.TraceProv.Tracer(name, opts...) +} + +// Close closes the observability primitives. +func (o *Observer) Close() { + for _, cancel := range o.closeFns { + cancel() + } +} + +// NewFake returns a fake observer that reports nothing. +// This is useful for tests. +func NewFake() *Observer { + log := logger.New(io.Discard, logger.LogfmtFormat(), logger.Error) + stats := statter.New(statter.DiscardReporter, time.Minute) + tracer := otel.GetTracerProvider() + + return New(log, stats, tracer) +} From 19e010789513a1218ba7648f55e5aafff97a9f9a Mon Sep 17 00:00:00 2001 From: Ullaakut Date: Mon, 2 Oct 2023 15:49:10 +0200 Subject: [PATCH 2/2] fix: add doc.go --- observe/doc.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 observe/doc.go diff --git a/observe/doc.go b/observe/doc.go new file mode 100644 index 0000000..a2b33e5 --- /dev/null +++ b/observe/doc.go @@ -0,0 +1,28 @@ +/* +Package observe implements a type that combines statter, logger and tracer. + +Example usage: + + func New(c *cli.Context, svc, version string) (*observe.Observer, error) { + log, logCancel, err := NewLogger(c, svc) + if err != nil { + return nil, err + } + + stats, statsCancel, err := NewStatter(c, log, svc) + if err != nil { + logCancel() + return nil, err + } + + tracer, traceCancel, err := NewTracer(c, log, svc, version) + if err != nil { + logCancel() + statsCancel() + return nil, err + } + + return observe.New(log, stats, tracer, traceCancel, statsCancel, logCancel), nil + } +*/ +package observe