1
0
mirror of https://github.com/golang/go synced 2024-11-06 03:26:15 -07:00
go/internal/telemetry/export/export.go
Ian Cottrell c4206d458c internal/telemetry: change tracing to be event based
We no longer use the span as the core type of tracing, instead that is an
artifact of the exporter, and start and end tracing is just event based.
This both makes the interface normalized, and also means the null exporter case
is considerably cheaper in memory and cpu.
See below for benchstat changes

name                 old time/op    new time/op    delta
TracingNoExporter-8    4.19µs ±12%    2.71µs ±11%  -35.33%  (p=0.000 n=20+20)
Tracing-8              24.1µs ± 3%     5.1µs ±17%  -78.66%  (p=0.000 n=16+20)

name                 old alloc/op   new alloc/op   delta
TracingNoExporter-8    2.32kB ± 0%    0.40kB ± 0%  -82.76%  (p=0.000 n=20+20)
Tracing-8              6.32kB ± 0%    2.32kB ± 0%  -63.30%  (p=0.000 n=20+20)

name                 old allocs/op  new allocs/op  delta
TracingNoExporter-8      35.0 ± 0%      15.0 ± 0%  -57.14%  (p=0.000 n=20+20)
Tracing-8                 215 ± 0%        35 ± 0%  -83.72%  (p=0.000 n=20+20)

Change-Id: I3cf25871fa49584819504b5c19aa580e5dd03395
Reviewed-on: https://go-review.googlesource.com/c/tools/+/221740
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
2020-03-04 02:41:40 +00:00

83 lines
1.9 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 export holds the definition of the telemetry Exporter interface,
// along with some simple implementations.
// Larger more complex exporters are in sub packages of their own.
package export
import (
"context"
"os"
"sync/atomic"
"time"
"unsafe"
"golang.org/x/tools/internal/telemetry"
)
type Exporter interface {
// ProcessEvent is a function that handles all events.
// Exporters may use information in the context to decide what to do with a
// given event.
ProcessEvent(context.Context, telemetry.Event) context.Context
Metric(context.Context, telemetry.MetricData)
}
var (
exporter unsafe.Pointer
)
func init() {
SetExporter(LogWriter(os.Stderr, true))
}
func SetExporter(e Exporter) {
p := unsafe.Pointer(&e)
if e == nil {
p = nil
}
atomic.StorePointer(&exporter, p)
}
func Tag(ctx context.Context, at time.Time, tags telemetry.TagList) {
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
if exporterPtr == nil {
return
}
// If context has a span we need to add the tags to it
span := GetSpan(ctx)
if span == nil {
return
}
if span.Start.IsZero() {
// span still being created, tag it directly
span.Tags = append(span.Tags, tags...)
return
}
// span in progress, add an event to the span
span.Events = append(span.Events, telemetry.Event{
At: at,
Tags: tags,
})
}
func ProcessEvent(ctx context.Context, event telemetry.Event) context.Context {
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
if exporterPtr == nil {
return ctx
}
// and now also hand the event of to the current exporter
return (*exporterPtr).ProcessEvent(ctx, event)
}
func Metric(ctx context.Context, data telemetry.MetricData) {
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
if exporterPtr == nil {
return
}
(*exporterPtr).Metric(ctx, data)
}