1
0
mirror of https://github.com/golang/go synced 2024-11-06 07:16:10 -07:00
go/internal/telemetry/event/export.go
Ian Cottrell cb106d260e internal/telemetry: allow ProcessEvent to modify the event
This allows early exporters to adjust the event for later ones.
This is used to lookup key values from the context if needed.
Also add a Query type event which is intended to perform all event
modifications but nothing else, and is used to lookup values from
the context. This cleans up a weirdness where the current lookup
presumes there will be an exporter with a matching mechanism.

Change-Id: I835d1e0b2511553c30f94b7becfe7b7b5462c111
Reviewed-on: https://go-review.googlesource.com/c/tools/+/223657
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
2020-03-18 13:22:01 +00:00

56 lines
1.5 KiB
Go

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package event
import (
"context"
"sync/atomic"
"unsafe"
)
type Exporter interface {
// ProcessEvent is a function that handles all events.
// This is called with all events that should be delivered to the exporter
// along with the context in which that event ocurred.
// This method is called synchronously from the event call site, so it should
// return quickly so as not to hold up user code.
ProcessEvent(context.Context, Event) (context.Context, Event)
Metric(context.Context, MetricData)
}
var (
exporter unsafe.Pointer
)
func SetExporter(e Exporter) {
p := unsafe.Pointer(&e)
if e == nil {
// &e is always valid, and so p is always valid, but for the early abort
// of ProcessEvent to be efficient it needs to make the nil check on the
// pointer without having to dereference it, so we make the nil interface
// also a nil pointer
p = nil
}
atomic.StorePointer(&exporter, p)
}
func ProcessEvent(ctx context.Context, ev Event) (context.Context, Event) {
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
if exporterPtr == nil {
return ctx, ev
}
// and now also hand the event of to the current exporter
return (*exporterPtr).ProcessEvent(ctx, ev)
}
func Metric(ctx context.Context, data MetricData) {
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
if exporterPtr == nil {
return
}
(*exporterPtr).Metric(ctx, data)
}