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