| 1 | // Copyright 2019 The Go Authors. All rights reserved. |
|---|---|
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | // Package metric aggregates events into metrics that can be exported. |
| 6 | package metric |
| 7 | |
| 8 | import ( |
| 9 | "context" |
| 10 | "sync" |
| 11 | "time" |
| 12 | |
| 13 | "golang.org/x/tools/internal/event" |
| 14 | "golang.org/x/tools/internal/event/core" |
| 15 | "golang.org/x/tools/internal/event/keys" |
| 16 | "golang.org/x/tools/internal/event/label" |
| 17 | ) |
| 18 | |
| 19 | var Entries = keys.New("metric_entries", "The set of metrics calculated for an event") |
| 20 | |
| 21 | type Config struct { |
| 22 | subscribers map[interface{}][]subscriber |
| 23 | } |
| 24 | |
| 25 | type subscriber func(time.Time, label.Map, label.Label) Data |
| 26 | |
| 27 | func (e *Config) subscribe(key label.Key, s subscriber) { |
| 28 | if e.subscribers == nil { |
| 29 | e.subscribers = make(map[interface{}][]subscriber) |
| 30 | } |
| 31 | e.subscribers[key] = append(e.subscribers[key], s) |
| 32 | } |
| 33 | |
| 34 | func (e *Config) Exporter(output event.Exporter) event.Exporter { |
| 35 | var mu sync.Mutex |
| 36 | return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { |
| 37 | if !event.IsMetric(ev) { |
| 38 | return output(ctx, ev, lm) |
| 39 | } |
| 40 | mu.Lock() |
| 41 | defer mu.Unlock() |
| 42 | var metrics []Data |
| 43 | for index := 0; ev.Valid(index); index++ { |
| 44 | l := ev.Label(index) |
| 45 | if !l.Valid() { |
| 46 | continue |
| 47 | } |
| 48 | id := l.Key() |
| 49 | if list := e.subscribers[id]; len(list) > 0 { |
| 50 | for _, s := range list { |
| 51 | metrics = append(metrics, s(ev.At(), lm, l)) |
| 52 | } |
| 53 | } |
| 54 | } |
| 55 | lm = label.MergeMaps(label.NewMap(Entries.Of(metrics)), lm) |
| 56 | return output(ctx, ev, lm) |
| 57 | } |
| 58 | } |
| 59 |
Members