// 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 metric aggregates events into metrics that can be exported. package metric import ( "context" "sync" "time" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/keys" "golang.org/x/tools/internal/event/label" ) var Entries = keys.New("metric_entries", "The set of metrics calculated for an event") type Config struct { subscribers map[interface{}][]subscriber } type subscriber func(time.Time, label.Map, label.Label) Data func (e *Config) subscribe(key label.Key, s subscriber) { if e.subscribers == nil { e.subscribers = make(map[interface{}][]subscriber) } e.subscribers[key] = append(e.subscribers[key], s) } func (e *Config) Exporter(output event.Exporter) event.Exporter { var mu sync.Mutex return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { if !event.IsMetric(ev) { return output(ctx, ev, lm) } mu.Lock() defer mu.Unlock() var metrics []Data for index := 0; ev.Valid(index); index++ { l := ev.Label(index) if !l.Valid() { continue } id := l.Key() if list := e.subscribers[id]; len(list) > 0 { for _, s := range list { metrics = append(metrics, s(ev.At(), lm, l)) } } } lm = label.MergeMaps(label.NewMap(Entries.Of(metrics)), lm) return output(ctx, ev, lm) } }