blob: 84c65215e2e50f85317bb5e9bb2f5062ab903c9f [file] [log] [blame]
// 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.
// +build !disable_events
package event
import (
// Exporter synchronizes the delivery of events to handlers.
type Exporter struct {
Now func() time.Time
mu sync.Mutex
handler Handler
lastEvent uint64
// contextKey is used as the key for storing a contextValue on the context.
type contextKeyType struct{}
var contextKey interface{} = contextKeyType{}
// contextValue is stored by value in the context to track the exporter and
// current parent event.
type contextValue struct {
exporter *Exporter
parent uint64
var (
defaultExporter unsafe.Pointer
// NewExporter creates an Exporter using the supplied handler.
// Event delivery is serialized to enable safe atomic handling.
func NewExporter(handler Handler) *Exporter {
return &Exporter{Now: time.Now, handler: handler}
func setDefaultExporter(e *Exporter) {
atomic.StorePointer(&defaultExporter, unsafe.Pointer(e))
func getDefaultExporter() *Exporter {
return (*Exporter)(atomic.LoadPointer(&defaultExporter))
func newContext(ctx context.Context, exporter *Exporter, parent uint64) context.Context {
return context.WithValue(ctx, contextKey, contextValue{exporter: exporter, parent: parent})
// FromContext returns the exporter and current trace for the supplied context.
func FromContext(ctx context.Context) (*Exporter, uint64) {
if v, ok := ctx.Value(contextKey).(contextValue); ok {
return v.exporter, v.parent
return getDefaultExporter(), 0
// prepare events before delivering to the underlying handler.
// The event will be assigned a new ID.
// If the event does not have a timestamp, and the exporter has a Now function
// then the timestamp will be updated.
// prepare must be called with the export mutex held.
func (e *Exporter) prepare(ev *Event) {
if e.Now != nil && ev.At.IsZero() {
ev.At = e.Now()
//TODO: decide how to control the enable/disable behaviour
func (e *Exporter) loggingEnabled() bool { return true }
func (e *Exporter) annotationsEnabled() bool { return true }
func (e *Exporter) tracingEnabled() bool { return true }
func (e *Exporter) metricsEnabled() bool { return true }