aboutsummaryrefslogtreecommitdiff
path: root/guix-build-coordinator/metrics.scm
diff options
context:
space:
mode:
Diffstat (limited to 'guix-build-coordinator/metrics.scm')
-rw-r--r--guix-build-coordinator/metrics.scm203
1 files changed, 137 insertions, 66 deletions
diff --git a/guix-build-coordinator/metrics.scm b/guix-build-coordinator/metrics.scm
index 00648d3..8878953 100644
--- a/guix-build-coordinator/metrics.scm
+++ b/guix-build-coordinator/metrics.scm
@@ -19,75 +19,146 @@
;;; <http://www.gnu.org/licenses/>.
(define-module (guix-build-coordinator metrics)
+ #:use-module (srfi srfi-9)
#:use-module (ice-9 match)
+ #:use-module (ice-9 exceptions)
#:use-module (guix-build-coordinator datastore)
- #:export (metrics))
+ #:export (make-metrics-registry
+ write-metrics
+
+ make-gauge-metric
+
+ metric-increment
+ metric-decrement
+ metric-set))
(define namespace
"guixbuildcoordinator")
-(define (format-metric namespace metric labels-and-values value)
- (simple-format
- #f
- "~A_~A~A ~A"
- namespace
- metric
- (if (null? labels-and-values)
- ""
- (string-append
- "{"
- (string-join (map
- (match-lambda
- ((label . value)
- (simple-format
- #f
- "~A=\"~A\""
- label value)))
- labels-and-values)
- ",")
- "}"))
- value))
-
-(define (metrics datastore)
- (string-join
- (append (list
- (format-metric
- namespace
- "builds_total"
- '()
- (datastore-count-builds datastore)))
- (map (match-lambda
- ((agent-id . count)
- (format-metric
- namespace
- "allocated_builds_total"
- `((agent_id . ,agent-id))
- count)))
- (datastore-count-allocated-builds datastore))
- (map (match-lambda
- (((agent-id result) . count)
- (format-metric
- namespace
- "build_results_total"
- `((agent_id . ,agent-id)
- (result . ,result))
- count)))
- (datastore-count-build-results datastore))
- (map (match-lambda
- (((agent-id reason) . count)
- (format-metric
- namespace
- "setup_failures_total"
- `((agent_id . ,agent-id)
- (reason . ,reason))
- count)))
- (datastore-count-setup-failures datastore))
- (map (match-lambda
- ((agent-id . count)
- (format-metric
- namespace
- "build_allocation_plan_total"
- `((agent_id . ,agent-id))
- count)))
- (datastore-count-build-allocation-plan-entries datastore)))
- "\n"))
+(define-record-type <metrics-registry>
+ (make-metrics-registry-record metrics-hash)
+ metrics-registry?
+ (metrics-hash metrics-registry-metrics-hash))
+
+(define (make-metrics-registry)
+ (make-metrics-registry-record (make-hash-table)))
+
+(define-record-type <metric>
+ (make-metric type name values registry docstring labels label-preset-values)
+ metric?
+ (type metric-type)
+ (name metric-name)
+ (values metric-values)
+ (registry metric-registry)
+ (docstring metric-docstring)
+ (labels metric-labels)
+ (label-preset-values metric-label-preset-values))
+
+(define (metrics-registry-add-metric registry name metric)
+ (let ((metrics-hash
+ (metrics-registry-metrics-hash registry)))
+ (when (hash-ref metrics-hash name)
+ (raise-exception
+ (make-exception-with-message
+ (simple-format #f "metric ~A already exists"
+ name))))
+
+ (hash-set! metrics-hash name metric)
+
+ metric))
+
+(define* (make-gauge-metric registry name
+ #:key
+ docstring
+ (labels '())
+ (label-preset-values '()))
+ (metrics-registry-add-metric
+ registry
+ name
+ (make-metric 'gauge
+ name
+ (make-hash-table)
+ registry
+ docstring
+ labels
+ label-preset-values)))
+
+(define (canonicalise-label-values-for-metric metric
+ label-values)
+ label-values)
+
+(define* (metric-increment metric
+ #:key
+ (by 1)
+ (label-values '()))
+ (unless (memq (metric-type metric)
+ '(counter gauge))
+ (error "can only increment counter and gauge metrics"))
+
+ (unless (positive? by)
+ (error "can only increment positive values"))
+
+ (let ((canonical-labels
+ (canonicalise-label-values-for-metric metric label-values))
+ (hash
+ (metric-values metric)))
+ (hash-set! hash
+ canonical-labels
+ (+ by
+ (or (hash-ref hash canonical-labels)
+ 0)))))
+
+(define* (metric-decrement metric
+ #:key
+ (by 1)
+ (label-values '()))
+ (unless (memq (metric-type metric)
+ '(gauge))
+ (error "can only increment gauge metrics"))
+
+ (let ((canonical-labels
+ (canonicalise-label-values-for-metric metric label-values))
+ (hash
+ (metric-values metric)))
+ (hash-set! hash
+ canonical-labels
+ (+ (* -1 by)
+ (or (hash-ref hash canonical-labels)
+ 0)))))
+
+(define* (metric-set metric value
+ #:key (label-values '()))
+ (unless (memq (metric-type metric)
+ '(gauge))
+ (error "can only set gauge metrics"))
+
+ (hash-set! (metric-values metric)
+ (canonicalise-label-values-for-metric metric label-values)
+ value))
+
+(define (write-metrics registry port)
+ (hash-for-each
+ (lambda (name metric)
+ (hash-for-each
+ (lambda (label-values value)
+ (simple-format
+ port
+ "~A~A ~A\n"
+ name
+ (if (null? label-values)
+ ""
+ (string-append
+ "{"
+ (string-join (map
+ (match-lambda
+ ((label . value)
+ (simple-format
+ #f
+ "~A=\"~A\""
+ label value)))
+ label-values)
+ ",")
+ "}"))
+ value))
+ (metric-values metric)))
+ (metrics-registry-metrics-hash registry)))