github.com/v2fly/tools@v0.100.0/internal/event/export/metric/exporter.go (about) 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 "github.com/v2fly/tools/internal/event" 14 "github.com/v2fly/tools/internal/event/core" 15 "github.com/v2fly/tools/internal/event/keys" 16 "github.com/v2fly/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 }