module metrics import sync.stdatomic struct CounterEntry { metric Metric index int } struct HistogramEntry { metric Metric pub mut: data shared []f64 } [heap] struct DefaultCollector { mut: // The mutex for counters also applies to counter_indexes. Both data // structuress are only ever updated together. Note that only registering a // new metric actually changes these; all operations on already existing // metrics use atomic operations on the elements of the counters array. counters shared []u64 counter_indexes map[string]CounterEntry histograms shared map[string]HistogramEntry } pub fn new_default_collector() &DefaultCollector { return &DefaultCollector{ counters: []u64{} counter_indexes: map[string]CounterEntry{} histograms: map[string]HistogramEntry{} } } pub fn (mut c DefaultCollector) counter_register(value u64, metric Metric) { lock c.counters { c.counters << value c.counter_indexes[metric.str()] = CounterEntry{ metric: metric index: c.counters.len - 1 } } } pub fn (c &DefaultCollector) counter_increment(metric Metric) { rlock c.counters { entry := c.counter_indexes[metric.str()] stdatomic.add_u64(&c.counters[entry.index], 1) } } pub fn (c &DefaultCollector) counter_decrement(metric Metric) { rlock c.counters { entry := c.counter_indexes[metric.str()] stdatomic.sub_u64(&c.counters[entry.index], 1) } } pub fn (c &DefaultCollector) counter_get(metric Metric) ?u64 { return rlock c.counters { entry := c.counter_indexes[metric.str()] or { return none } stdatomic.load_u64(&c.counters[entry.index]) } } pub fn (mut c DefaultCollector) histogram_register(metric Metric) { lock c.histograms { c.histograms[metric.str()] = HistogramEntry{ metric: metric data: []f64{} } } } pub fn (c &DefaultCollector) histogram_add(value f64, metric Metric) { entry := rlock c.histograms { c.histograms[metric.str()] } lock entry.data { entry.data << value } } pub fn (c &DefaultCollector) histogram_get(metric Metric) ?[]f64 { entry := rlock c.histograms { c.histograms[metric.str()] or { return none } } return rlock entry.data { // Return a clone of the data to prevent user from altering // internal structure entry.data.clone() } }