forked from awaragi/prometheus-mssql-exporter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcustom_metrics.js
135 lines (126 loc) · 4.2 KB
/
custom_metrics.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* Functions for reading and parsing yaml file as additional metric queries
*/
const debug = require("debug")("metrics");
const fs = require('fs');
const yaml = require('js-yaml');
const client = require('prom-client');
/**
* Function that reads and parses a yaml file into metric objects
*
* @param yaml_path the path to the yaml file
*
* @returns [Array of query-based metrics objects, Error]
*/
function parse_metrics(yaml_path) {
let metrics = []
let file, raw_metrics
try {
file = fs.readFileSync(yaml_path, 'utf8')
} catch (error) {
return [[], error]
}
try {
raw_metrics = yaml.load(file)
} catch (error) {
return [[], error]
}
for (let raw_metric in raw_metrics) {
metrics.push(build_metric_object(raw_metrics[raw_metric]))
}
return [metrics, null]
}
/**
* Function that reads JS object and returns metric object ussable in index.js
*
* @param metric_json Metric in json form
* example:
* {
* metrics: [ {
* name: 'mssql_instance_local_time_custom',
* help: 'Number of seconds since epoch on local instance (custom version)'
* } ],
* query: 'SELECT DATEDIFF(second, \'19700101\', GETUTCDATE())',
* collect: [ {
* metrics: [ {
* position: 0
* } ]
* } ]
* }
*
* @returns object usable by index.js; see metrics.js for examples
*/
function build_metric_object(metric_json) {
gauges_object = {}
for (let raw_gauge of metric_json.metrics) {
gauges_object[raw_gauge["name"]] = new client.Gauge(raw_gauge)
}
return {
metrics: gauges_object,
query: metric_json["query"],
collect: build_collect_function(metric_json)
}
}
/**
* Function that reads JS object and returns collect function
*
* @param metric_json Metric in json forml; see queries.yaml for examples and QUERIES.md for documentation
*
* @returns function
*/
function build_collect_function(metric_json) {
function collector (rows, metrics) {
// Metrics are returned as a series of either one or more rows
for (let row_pos = 0; row_pos < rows.length; row_pos++) {
let row = rows[row_pos];
// For each row, we will collect each metric, including the labels specified
for (let i = 0; i < metric_json.collect.length; i++) {
let labels = {}
if (metric_json.collect[i].shared_labels) {
labels = add_labels(labels, metric_json.collect[i].shared_labels, row)
}
for (let position_obj of metric_json.collect[i].metrics) {
let fetched_value = row[position_obj.position].value;
if (position_obj.name) {
debug("Fetch ", metric_json.metrics[i].name, position_obj.name, fetched_value);
} else {
debug("Fetch ", metric_json.metrics[i].name, fetched_value);
}
if (position_obj.additional_labels) {
labels = add_labels(labels, position_obj.additional_labels, row)
}
if (Object.keys(labels).length != 0) {
metrics[metric_json.metrics[i].name].set(labels, fetched_value);
} else {
metrics[metric_json.metrics[i].name].set(fetched_value);
}
}
}
}
}
return collector
}
/**
* Function for parsing labels for metrics
*
* @param labels dictionary to add to
* @param raw_labels raw labels JSON
* @param row current MSSQL row
*
* @returns labels_return dictionary of labels (cloned from original)
*/
function add_labels(labels, raw_labels, row) {
labels_return = Object.assign({}, labels);
for (let label_obj of raw_labels) {
// Labels can either be defined or dynamically collected from the rows
if (label_obj.value) {
labels_return[label_obj.key] = label_obj.value
} else {
labels_return[label_obj.key] = row[label_obj.position].value
}
}
return labels_return
}
module.exports = {
parse_metrics: parse_metrics,
};