opentelemetry.template
import (
"time"
"fmt"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/label"
)
{{ $decorator := (or .Vars.DecoratorName (printf "%sWithTelemetry" .Interface.Name)) }}
// {{$decorator}} implements {{.Interface.Type}} interface with all methods wrapped
// with open telemetry metrics
type {{$decorator}} struct {
base {{.Interface.Type}}
methodCounters map[string]metric.BoundInt64Counter
errCounters map[string]metric.BoundInt64Counter
methodTimeValueRecorders map[string]metric.BoundInt64ValueRecorder
}
// New{{.Interface.Name}}WithTelemetry returns an instance of the {{.Interface.Type}} decorated with open telemetry timing and count metrics
func New{{$decorator}}(base {{.Interface.Type}}, name string, meter metric.Meter) {{$decorator}} {
return {{$decorator}} {
base: base,
methodCounters: new{{.Interface.Name}}MethodCounters("Calls", name, meter),
errCounters: new{{.Interface.Name}}MethodCounters("Errors", name, meter),
methodTimeValueRecorders: new{{.Interface.Name}}MethodTimeValueRecorders(name, meter),
}
}
func new{{.Interface.Name}}MethodTimeValueRecorders(appName string, meter metric.Meter) (boundTimeValueRecorders map[string]metric.BoundInt64ValueRecorder) {
boundTimeValueRecorders = make(map[string]metric.BoundInt64ValueRecorder)
mt := metric.Must(meter)
{{ $ifaceName := .Interface.Name }}
{{range $method := .Interface.Methods}}
n{{$method.Name}}ValRecorder := []rune("{{printf "%s_%s_ProcessingTimeMillis" $ifaceName $method.Name}}")
n{{$method.Name}}ValRecorder[0] = unicode.ToLower(n{{$method.Name}}ValRecorder[0])
m{{$method.Name}} := mt.NewInt64ValueRecorder(string(n{{$method.Name}}ValRecorder))
boundTimeValueRecorders["{{$method.Name}}"] = m{{$method.Name}}.Bind(label.String("name", appName))
{{end}}
return boundTimeValueRecorders
}
func new{{.Interface.Name}}MethodCounters(suffix string, appName string, meter metric.Meter) (boundCounters map[string]metric.BoundInt64Counter) {
boundCounters = make(map[string]metric.BoundInt64Counter)
mt := metric.Must(meter)
{{ $ifaceName := .Interface.Name }}
{{range $method := .Interface.Methods}}
n{{$method.Name}}Counter := []rune("{{printf "%s_%s_" $ifaceName $method.Name}}" + suffix)
n{{$method.Name}}Counter[0] = unicode.ToLower(n{{$method.Name}}Counter[0])
c{{$method.Name}} := mt.NewInt64Counter(string(n{{$method.Name}}Counter))
boundCounters["{{$method.Name}}"] = c{{$method.Name}}.Bind(label.String("name", appName))
{{end}}
return boundCounters
}
{{range $method := .Interface.Methods}}
// {{$method.Name}} implements {{$.Interface.Type}}
func (_d {{$decorator}}) {{$method.Declaration}} {
_since := time.Now()
defer func() {
{{- if $method.ReturnsError}}
if err != nil {
errCounter := _d.errCounters["{{$method.Name}}"]
errCounter.Add(context.Background(), 1)
}
{{end}}
methodCounter := _d.methodCounters["{{$method.Name}}"]
methodCounter.Add(context.Background(), 1)
methodTimeMeasure := _d.methodTimeValueRecorders["{{$method.Name}}"]
methodTimeMeasure.Record(context.Background(), time.Since(_since).Milliseconds())
}()
{{$method.Pass "_d.base."}}
}
{{end}}