feat: added gauge type & some tests
							parent
							
								
									a1049943a4
								
							
						
					
					
						commit
						52fbf8ce5d
					
				| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					*.c
 | 
				
			||||||
 | 
					*.so
 | 
				
			||||||
							
								
								
									
										103
									
								
								collector.v
								
								
								
								
							
							
						
						
									
										103
									
								
								collector.v
								
								
								
								
							| 
						 | 
					@ -2,12 +2,12 @@ module metrics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sync.stdatomic
 | 
					import sync.stdatomic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CounterEntry {
 | 
					struct Counter {
 | 
				
			||||||
	metric Metric
 | 
						metric Metric
 | 
				
			||||||
	index  int
 | 
						data   u64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct HistogramEntry {
 | 
					struct FloatSeries {
 | 
				
			||||||
	metric Metric
 | 
						metric Metric
 | 
				
			||||||
pub mut:
 | 
					pub mut:
 | 
				
			||||||
	data shared []f64
 | 
						data shared []f64
 | 
				
			||||||
| 
						 | 
					@ -16,72 +16,66 @@ pub mut:
 | 
				
			||||||
[heap]
 | 
					[heap]
 | 
				
			||||||
struct DefaultCollector {
 | 
					struct DefaultCollector {
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
	// The mutex for counters also applies to counter_indexes. Both data
 | 
						counters   shared map[string]&Counter
 | 
				
			||||||
	// structuress are only ever updated together. Note that only registering a
 | 
						histograms shared map[string]&FloatSeries
 | 
				
			||||||
	// new metric actually changes these; all operations on already existing
 | 
						gauges     shared map[string]&FloatSeries
 | 
				
			||||||
	// 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 {
 | 
					pub fn new_default_collector() &DefaultCollector {
 | 
				
			||||||
	return &DefaultCollector{
 | 
						return &DefaultCollector{
 | 
				
			||||||
		counters: []u64{}
 | 
							counters: map[string]&Counter{}
 | 
				
			||||||
		counter_indexes: map[string]CounterEntry{}
 | 
							histograms: map[string]&FloatSeries{}
 | 
				
			||||||
		histograms: map[string]HistogramEntry{}
 | 
							gauges: map[string]&FloatSeries{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut c DefaultCollector) counter_register(value u64, metric Metric) {
 | 
					pub fn (mut c DefaultCollector) counter_register(value u64, metric Metric) {
 | 
				
			||||||
	lock c.counters {
 | 
						lock c.counters {
 | 
				
			||||||
		c.counters << value
 | 
							c.counters[metric.str()] = &Counter{
 | 
				
			||||||
 | 
					 | 
				
			||||||
		c.counter_indexes[metric.str()] = CounterEntry{
 | 
					 | 
				
			||||||
			metric: metric
 | 
								metric: metric
 | 
				
			||||||
			index: c.counters.len - 1
 | 
								data: value
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &DefaultCollector) counter_increment(metric Metric) {
 | 
					pub fn (c &DefaultCollector) counter_increment(metric Metric) {
 | 
				
			||||||
	rlock c.counters {
 | 
						rlock c.counters {
 | 
				
			||||||
		entry := c.counter_indexes[metric.str()]
 | 
							entry := c.counters[metric.str()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		stdatomic.add_u64(&c.counters[entry.index], 1)
 | 
							stdatomic.add_u64(&entry.data, 1)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &DefaultCollector) counter_get(metric Metric) ?u64 {
 | 
					pub fn (c &DefaultCollector) counter_get(metric Metric) ?u64 {
 | 
				
			||||||
	return rlock c.counters {
 | 
						return rlock c.counters {
 | 
				
			||||||
		entry := c.counter_indexes[metric.str()] or { return none }
 | 
							entry := c.counters[metric.str()] or { return none }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		stdatomic.load_u64(&c.counters[entry.index])
 | 
							stdatomic.load_u64(&entry.data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &DefaultCollector) counters() []Metric {
 | 
					pub fn (c &DefaultCollector) counters() []Metric {
 | 
				
			||||||
    mut metrics := []Metric{}
 | 
						mut metrics := []Metric{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rlock c.counters {
 | 
						rlock c.counters {
 | 
				
			||||||
        for _, entry in c.counter_indexes {
 | 
							for _, entry in c.counters {
 | 
				
			||||||
            metrics << entry.metric
 | 
								metrics << entry.metric
 | 
				
			||||||
        }
 | 
							}
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return metrics
 | 
						return metrics
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut c DefaultCollector) histogram_register(metric Metric) {
 | 
					pub fn (mut c DefaultCollector) histogram_register(metric Metric) {
 | 
				
			||||||
	lock c.histograms {
 | 
						lock c.histograms {
 | 
				
			||||||
		c.histograms[metric.str()] = HistogramEntry{
 | 
							c.histograms[metric.str()] = &FloatSeries{
 | 
				
			||||||
			metric: metric
 | 
								metric: metric
 | 
				
			||||||
			data: []f64{}
 | 
								data: []f64{}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &DefaultCollector) histogram_add(value f64, metric Metric) {
 | 
					pub fn (c &DefaultCollector) histogram_record(value f64, metric Metric) {
 | 
				
			||||||
	entry := rlock c.histograms {
 | 
						entry := rlock c.histograms {
 | 
				
			||||||
		c.histograms[metric.str()]
 | 
							c.histograms[metric.str()]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -102,3 +96,52 @@ pub fn (c &DefaultCollector) histogram_get(metric Metric) ?[]f64 {
 | 
				
			||||||
		entry.data.clone()
 | 
							entry.data.clone()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (mut c DefaultCollector) gauge_register(value f64, metric Metric) {
 | 
				
			||||||
 | 
						lock c.gauges {
 | 
				
			||||||
 | 
							c.gauges[metric.str()] = &FloatSeries{
 | 
				
			||||||
 | 
								metric: metric
 | 
				
			||||||
 | 
								data: [value]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &DefaultCollector) gauge_add(value f64, metric Metric) {
 | 
				
			||||||
 | 
						entry := rlock c.gauges {
 | 
				
			||||||
 | 
							c.gauges[metric.str()]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lock entry.data {
 | 
				
			||||||
 | 
							entry.data[0] += value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &DefaultCollector) gauge_sub(value f64, metric Metric) {
 | 
				
			||||||
 | 
						entry := rlock c.gauges {
 | 
				
			||||||
 | 
							c.gauges[metric.str()]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lock entry.data {
 | 
				
			||||||
 | 
							entry.data[0] -= value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &DefaultCollector) gauge_set(value f64, metric Metric) {
 | 
				
			||||||
 | 
						entry := rlock c.gauges {
 | 
				
			||||||
 | 
							c.gauges[metric.str()]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lock entry.data {
 | 
				
			||||||
 | 
							entry.data[0] = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &DefaultCollector) gauge_get(metric Metric) ?f64 {
 | 
				
			||||||
 | 
						entry := rlock c.gauges {
 | 
				
			||||||
 | 
							c.gauges[metric.str()]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rlock entry.data {
 | 
				
			||||||
 | 
							entry.data[0]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					module metrics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_implements_interface() {
 | 
				
			||||||
 | 
						_ := MetricsCollector(new_default_collector())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_null_implements_interface() {
 | 
				
			||||||
 | 
						_ := MetricsCollector(new_null_collector())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_counter_increment() {
 | 
				
			||||||
 | 
						mut m := new_default_collector()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.counter_register(0, name: 'test')
 | 
				
			||||||
 | 
						m.counter_increment(name: 'test')
 | 
				
			||||||
 | 
						assert m.counter_get(name: 'test')? == u64(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.counter_increment(name: 'test')
 | 
				
			||||||
 | 
						assert m.counter_get(name: 'test')? == u64(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Test with labels
 | 
				
			||||||
 | 
					    metric := Metric{
 | 
				
			||||||
 | 
					        name: 'test2'
 | 
				
			||||||
 | 
					        labels: [['hi', 'label']!, ['hi2', 'label2']!]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.counter_register(15, metric)
 | 
				
			||||||
 | 
						m.counter_increment(metric)
 | 
				
			||||||
 | 
						assert m.counter_get(metric)? == u64(16)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_histogram() {
 | 
				
			||||||
 | 
						mut m := new_default_collector()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.histogram_register(name: 'test')
 | 
				
			||||||
 | 
					    m.histogram_record(5.0, name: 'test')
 | 
				
			||||||
 | 
					    assert m.histogram_get(name: 'test')? == [5.0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.histogram_record(7.0, name: 'test')
 | 
				
			||||||
 | 
					    assert m.histogram_get(name: 'test')? == [5.0, 7.0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Test with labels
 | 
				
			||||||
 | 
					    metric := Metric{
 | 
				
			||||||
 | 
					        name: 'test2'
 | 
				
			||||||
 | 
					        labels: [['hi', 'label']!, ['hi2', 'label2']!]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.histogram_register(metric)
 | 
				
			||||||
 | 
					    m.histogram_record(5.0, metric)
 | 
				
			||||||
 | 
					    assert m.histogram_get(metric)? == [5.0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.histogram_record(7.0, metric)
 | 
				
			||||||
 | 
					    assert m.histogram_get(metric)? == [5.0, 7.0]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_gauge_add() {
 | 
				
			||||||
 | 
						mut m := new_default_collector()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.gauge_register(0.0, name: 'test')
 | 
				
			||||||
 | 
					    m.gauge_add(5.0, name: 'test')
 | 
				
			||||||
 | 
					    assert m.gauge_get(name: 'test')? == 5.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Test with labels
 | 
				
			||||||
 | 
					    metric := Metric{
 | 
				
			||||||
 | 
					        name: 'test2'
 | 
				
			||||||
 | 
					        labels: [['hi', 'label']!, ['hi2', 'label2']!]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.gauge_register(3.0, metric)
 | 
				
			||||||
 | 
					    m.gauge_add(5.0, metric)
 | 
				
			||||||
 | 
					    assert m.gauge_get(metric)? == 8.0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_gauge_sub() {
 | 
				
			||||||
 | 
						mut m := new_default_collector()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.gauge_register(0.0, name: 'test')
 | 
				
			||||||
 | 
					    m.gauge_sub(5.0, name: 'test')
 | 
				
			||||||
 | 
					    assert m.gauge_get(name: 'test')? == -5.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Test with labels
 | 
				
			||||||
 | 
					    metric := Metric{
 | 
				
			||||||
 | 
					        name: 'test2'
 | 
				
			||||||
 | 
					        labels: [['hi', 'label']!, ['hi2', 'label2']!]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.gauge_register(3.0, metric)
 | 
				
			||||||
 | 
					    m.gauge_sub(5.0, metric)
 | 
				
			||||||
 | 
					    assert m.gauge_get(metric)? == -2.0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_gauge_set() {
 | 
				
			||||||
 | 
						mut m := new_default_collector()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.gauge_register(0.0, name: 'test')
 | 
				
			||||||
 | 
					    m.gauge_set(3.0, name: 'test')
 | 
				
			||||||
 | 
					    assert m.gauge_get(name: 'test')? == 3.0
 | 
				
			||||||
 | 
					    m.gauge_set(5.0, name: 'test')
 | 
				
			||||||
 | 
					    assert m.gauge_get(name: 'test')? == 5.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Test with labels
 | 
				
			||||||
 | 
					    metric := Metric{
 | 
				
			||||||
 | 
					        name: 'test2'
 | 
				
			||||||
 | 
					        labels: [['hi', 'label']!, ['hi2', 'label2']!]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m.gauge_register(0.0, metric)
 | 
				
			||||||
 | 
					    m.gauge_set(3.0, metric)
 | 
				
			||||||
 | 
					    assert m.gauge_get(metric)? == 3.0
 | 
				
			||||||
 | 
					    m.gauge_set(5.0, metric)
 | 
				
			||||||
 | 
					    assert m.gauge_get(metric)? == 5.0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,14 +0,0 @@
 | 
				
			||||||
module metrics
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn test_counter_increment() {
 | 
					 | 
				
			||||||
	mut m := new_default_collector()
 | 
					 | 
				
			||||||
	m.counter_register(0, name: 'test')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.counter_increment(name: 'test')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert m.counter_get(name: 'test')? == u64(1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.counter_increment(name: 'test')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert m.counter_get(name: 'test')? == u64(2)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					module exporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import io
 | 
				
			||||||
 | 
					import metrics { MetricsCollector }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub interface MetricsExporter {
 | 
				
			||||||
 | 
					    load(collector MetricsCollector)
 | 
				
			||||||
 | 
					    export_to_writer(writer io.Writer) !
 | 
				
			||||||
 | 
					    export_to_string() string !
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					module exporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct PrometheusExporter {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								metrics.v
								
								
								
								
							
							
						
						
									
										14
									
								
								metrics.v
								
								
								
								
							| 
						 | 
					@ -20,11 +20,17 @@ pub fn (m &Metric) str() string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub interface MetricsCollector {
 | 
					pub interface MetricsCollector {
 | 
				
			||||||
	counter_register(value u64, metric Metric)
 | 
					 | 
				
			||||||
	counter_increment(metric Metric)
 | 
						counter_increment(metric Metric)
 | 
				
			||||||
	counter_get(metric Metric) ?u64
 | 
						counter_get(metric Metric) ?u64
 | 
				
			||||||
    counters() []Metric
 | 
						counters() []Metric
 | 
				
			||||||
 | 
						histogram_record(value f64, metric Metric)
 | 
				
			||||||
 | 
						histogram_get(metric Metric) ?[]f64
 | 
				
			||||||
 | 
						gauge_add(value f64, metric Metric)
 | 
				
			||||||
 | 
						gauge_sub(value f64, metric Metric)
 | 
				
			||||||
 | 
						gauge_set(value f64, metric Metric)
 | 
				
			||||||
 | 
						gauge_get(metric Metric) ?f64
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
 | 
						counter_register(value u64, metric Metric)
 | 
				
			||||||
	histogram_register(metric Metric)
 | 
						histogram_register(metric Metric)
 | 
				
			||||||
	histogram_add(value f64, metric Metric)
 | 
						gauge_register(value f64, metric Metric)
 | 
				
			||||||
	histogram_get(metric Metric) ?
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								null.v
								
								
								
								
							
							
						
						
									
										18
									
								
								null.v
								
								
								
								
							| 
						 | 
					@ -15,12 +15,26 @@ pub fn (c &NullCollector) counter_get(metric Metric) ?u64 {
 | 
				
			||||||
	return none
 | 
						return none
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &NullCollector) counters() []Metric { return [] }
 | 
					pub fn (c &NullCollector) counters() []Metric {
 | 
				
			||||||
 | 
						return []
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &NullCollector) histogram_register(metric Metric) {}
 | 
					pub fn (c &NullCollector) histogram_register(metric Metric) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &NullCollector) histogram_add(value f64, metric Metric) {}
 | 
					pub fn (c &NullCollector) histogram_record(value f64, metric Metric) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (c &NullCollector) histogram_get(metric Metric) ?[]f64 {
 | 
					pub fn (c &NullCollector) histogram_get(metric Metric) ?[]f64 {
 | 
				
			||||||
	return none
 | 
						return none
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &NullCollector) gauge_register(value f64, metric Metric) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &NullCollector) gauge_add(value f64, metric Metric) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &NullCollector) gauge_sub(value f64, metric Metric) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &NullCollector) gauge_set(value f64, metric Metric) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (c &NullCollector) gauge_get(metric Metric) ?f64 {
 | 
				
			||||||
 | 
						return none
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue