module metrics struct Counter { metric Metric mut: data u64 } struct Gauge { metric Metric pub mut: data f64 } struct Histogram { metric Metric pub mut: total_count u64 sum f64 buckets []f64 bucket_counts []u64 } [heap] struct DefaultCollector { mut: buckets map[string][]f64 counters shared map[string]&Counter histograms shared map[string]&Histogram gauges shared map[string]&Gauge } pub fn new_default_collector() &DefaultCollector { return &DefaultCollector{ buckets: map[string][]f64{} counters: map[string]&Counter{} histograms: map[string]&Histogram{} gauges: map[string]&Gauge{} } } pub fn (mut c DefaultCollector) counter_increment(metric Metric) { lock c.counters { mut entry := c.counters[metric.str()] or { counter := &Counter{ metric: metric data: 0 } c.counters[metric.str()] = counter counter } entry.data += 1 } } pub fn (mut c DefaultCollector) counter_set(value u64, metric Metric) { lock c.counters { mut entry := c.counters[metric.str()] or { counter := &Counter{ metric: metric data: 0 } c.counters[metric.str()] = counter counter } entry.data = value } } pub fn (c &DefaultCollector) counter_get(metric Metric) ?u64 { return rlock c.counters { entry := c.counters[metric.str()] or { return none } entry.data } } pub fn (c &DefaultCollector) counters() []Metric { mut metrics := []Metric{} rlock c.counters { for _, entry in c.counters { metrics << entry.metric } } return metrics } pub fn (mut c DefaultCollector) histogram_buckets_set(name string, buckets []f64) { lock c.histograms { c.buckets[name] = buckets } } pub fn (mut c DefaultCollector) histogram_record(value f64, metric Metric) { lock c.histograms { mut entry := c.histograms[metric.str()] or { buckets := c.buckets[metric.name] or { [] } hist := &Histogram{ metric: metric buckets: buckets bucket_counts: []u64{len: buckets.len, init: 0} } c.histograms[metric.str()] = hist hist } entry.sum += value entry.total_count += 1 mut i := entry.buckets.len - 1 for i >= 0 && value <= entry.buckets[i] { entry.bucket_counts[i]++ i -= 1 } } } pub fn (c &DefaultCollector) histogram_get(metric Metric) ?Histogram { return rlock c.histograms { entry := c.histograms[metric.str()] or { return none } // Return a clone of the data to prevent user from altering // internal structure Histogram{ metric: metric total_count: entry.total_count sum: entry.sum buckets: entry.buckets.clone() bucket_counts: entry.bucket_counts.clone() } } } pub fn (mut c DefaultCollector) gauge_add(value f64, metric Metric) { lock c.gauges { mut entry := c.gauges[metric.str()] or { gauge := &Gauge{ metric: metric data: 0.0 } c.gauges[metric.str()] = gauge gauge } entry.data += value } } pub fn (mut c DefaultCollector) gauge_sub(value f64, metric Metric) { lock c.gauges { mut entry := c.gauges[metric.str()] or { gauge := &Gauge{ metric: metric data: 0.0 } c.gauges[metric.str()] = gauge gauge } entry.data -= value } } pub fn (mut c DefaultCollector) gauge_set(value f64, metric Metric) { lock c.gauges { mut entry := c.gauges[metric.str()] or { gauge := &Gauge{ metric: metric data: 0.0 } c.gauges[metric.str()] = gauge gauge } entry.data = value } } pub fn (c &DefaultCollector) gauge_get(metric Metric) ?f64 { return rlock c.gauges { entry := c.gauges[metric.str()] or { return none } entry.data } } pub fn (c &DefaultCollector) histograms() []Metric { mut metrics := []Metric{} rlock c.histograms { for _, entry in c.histograms { metrics << entry.metric } } return metrics } pub fn (c &DefaultCollector) gauges() []Metric { mut metrics := []Metric{} rlock c.gauges { for _, entry in c.gauges { metrics << entry.metric } } return metrics }