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
 | 
			
		||||
 | 
			
		||||
struct CounterEntry {
 | 
			
		||||
struct Counter {
 | 
			
		||||
	metric Metric
 | 
			
		||||
	index  int
 | 
			
		||||
	data   u64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct HistogramEntry {
 | 
			
		||||
struct FloatSeries {
 | 
			
		||||
	metric Metric
 | 
			
		||||
pub mut:
 | 
			
		||||
	data shared []f64
 | 
			
		||||
| 
						 | 
				
			
			@ -16,72 +16,66 @@ pub mut:
 | 
			
		|||
[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
 | 
			
		||||
	counters   shared map[string]&Counter
 | 
			
		||||
	histograms shared map[string]&FloatSeries
 | 
			
		||||
	gauges     shared map[string]&FloatSeries
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn new_default_collector() &DefaultCollector {
 | 
			
		||||
	return &DefaultCollector{
 | 
			
		||||
		counters: []u64{}
 | 
			
		||||
		counter_indexes: map[string]CounterEntry{}
 | 
			
		||||
		histograms: map[string]HistogramEntry{}
 | 
			
		||||
		counters: map[string]&Counter{}
 | 
			
		||||
		histograms: map[string]&FloatSeries{}
 | 
			
		||||
		gauges: map[string]&FloatSeries{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut c DefaultCollector) counter_register(value u64, metric Metric) {
 | 
			
		||||
	lock c.counters {
 | 
			
		||||
		c.counters << value
 | 
			
		||||
 | 
			
		||||
		c.counter_indexes[metric.str()] = CounterEntry{
 | 
			
		||||
		c.counters[metric.str()] = &Counter{
 | 
			
		||||
			metric: metric
 | 
			
		||||
			index: c.counters.len - 1
 | 
			
		||||
			data: value
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (c &DefaultCollector) counter_increment(metric Metric) {
 | 
			
		||||
	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 {
 | 
			
		||||
	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 {
 | 
			
		||||
    mut metrics := []Metric{}
 | 
			
		||||
	mut metrics := []Metric{}
 | 
			
		||||
 | 
			
		||||
    rlock c.counters {
 | 
			
		||||
        for _, entry in c.counter_indexes {
 | 
			
		||||
            metrics << entry.metric
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
	rlock c.counters {
 | 
			
		||||
		for _, entry in c.counters {
 | 
			
		||||
			metrics << entry.metric
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    return metrics
 | 
			
		||||
	return metrics
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut c DefaultCollector) histogram_register(metric Metric) {
 | 
			
		||||
	lock c.histograms {
 | 
			
		||||
		c.histograms[metric.str()] = HistogramEntry{
 | 
			
		||||
		c.histograms[metric.str()] = &FloatSeries{
 | 
			
		||||
			metric: metric
 | 
			
		||||
			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 {
 | 
			
		||||
		c.histograms[metric.str()]
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -102,3 +96,52 @@ pub fn (c &DefaultCollector) histogram_get(metric Metric) ?[]f64 {
 | 
			
		|||
		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 {
 | 
			
		||||
	counter_register(value u64, metric Metric)
 | 
			
		||||
	counter_increment(metric Metric)
 | 
			
		||||
	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_add(value f64, metric Metric)
 | 
			
		||||
	histogram_get(metric Metric) ?
 | 
			
		||||
	gauge_register(value f64, metric Metric)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								null.v
								
								
								
								
							
							
						
						
									
										18
									
								
								null.v
								
								
								
								
							| 
						 | 
				
			
			@ -15,12 +15,26 @@ pub fn (c &NullCollector) counter_get(metric Metric) ?u64 {
 | 
			
		|||
	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_add(value f64, metric Metric) {}
 | 
			
		||||
pub fn (c &NullCollector) histogram_record(value f64, metric Metric) {}
 | 
			
		||||
 | 
			
		||||
pub fn (c &NullCollector) histogram_get(metric Metric) ?[]f64 {
 | 
			
		||||
	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