1
- import json from "json-stable-stringify" ;
2
1
import { EventEmitter } from "events" ;
3
- import type { JSONValue } from "@cocalc/util/types " ;
4
- import { ConatError } from "@cocalc/conat/core/client" ;
2
+ import json from "json-stable-stringify " ;
3
+
5
4
import { getLogger } from "@cocalc/conat/client" ;
5
+ import { ConatError } from "@cocalc/conat/core/client" ;
6
+ import type { JSONValue } from "@cocalc/util/types" ;
7
+ import { Metrics } from "../types" ;
6
8
7
9
const logger = getLogger ( "monitor:usage" ) ;
8
10
@@ -17,6 +19,9 @@ export class UsageMonitor extends EventEmitter {
17
19
private options : Options ;
18
20
private total = 0 ;
19
21
private perUser : { [ user : string ] : number } = { } ;
22
+ // metrics will be picked up periodically and exposed via e.g. prometheus
23
+ private countDeny = 0 ;
24
+ private metrics : Metrics = { } ;
20
25
21
26
constructor ( options : Options ) {
22
27
super ( ) ;
@@ -38,27 +43,53 @@ export class UsageMonitor extends EventEmitter {
38
43
39
44
private initLogging = ( ) => {
40
45
const { log } = this . options ;
41
- if ( log == null ) {
42
- return ;
43
- }
46
+
47
+ // Record metrics for all events (even if logging is disabled)
44
48
this . on ( "total" , ( total , limit ) => {
45
- log ( "usage" , this . options . resource , { total, limit } ) ;
49
+ this . metrics [ "total:count" ] = total ;
50
+ this . metrics [ "total:limit" ] = limit ;
51
+ if ( log ) {
52
+ log ( "usage" , this . options . resource , { total, limit } ) ;
53
+ }
46
54
} ) ;
47
55
this . on ( "add" , ( user , count , limit ) => {
48
- log ( "usage" , this . options . resource , "add" , { user, count, limit } ) ;
56
+ // this.metrics["add:count"] = count;
57
+ // this.metrics["add:limit"] = limit;
58
+ if ( log ) {
59
+ log ( "usage" , this . options . resource , "add" , { user, count, limit } ) ;
60
+ }
49
61
} ) ;
50
62
this . on ( "delete" , ( user , count , limit ) => {
51
- log ( "usage" , this . options . resource , "delete" , { user, count, limit } ) ;
63
+ // this.metrics["delete:count"] = count;
64
+ // this.metrics["delete:limit"] = limit;
65
+ if ( log ) {
66
+ log ( "usage" , this . options . resource , "delete" , { user, count, limit } ) ;
67
+ }
52
68
} ) ;
53
69
this . on ( "deny" , ( user , limit , type ) => {
54
- log ( "usage" , this . options . resource , "not allowed due to hitting limit" , {
55
- type,
56
- user,
57
- limit,
58
- } ) ;
70
+ this . countDeny += 1 ;
71
+ this . metrics [ "deny:count" ] = this . countDeny ;
72
+ this . metrics [ "deny:limit" ] = limit ;
73
+ if ( log ) {
74
+ log (
75
+ "usage" ,
76
+ this . options . resource ,
77
+ "not allowed due to hitting limit" ,
78
+ {
79
+ type,
80
+ user,
81
+ limit,
82
+ } ,
83
+ ) ;
84
+ }
59
85
} ) ;
60
86
} ;
61
87
88
+ // we return a copy
89
+ getMetrics = ( ) => {
90
+ return { ...this . metrics } ;
91
+ } ;
92
+
62
93
add = ( user : JSONValue ) => {
63
94
const u = this . toJson ( user ) ;
64
95
let count = this . perUser [ u ] ?? 0 ;
0 commit comments