Skip to content

Commit

Permalink
Merge pull request #304 from matrix-org/hs/async-metrics
Browse files Browse the repository at this point in the history
Collectors can now be async
  • Loading branch information
Half-Shot authored Jan 29, 2021
2 parents 1a0e209 + 51846f4 commit ee19602
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 14 deletions.
1 change: 1 addition & 0 deletions changelog.d/304.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fetch metrics asynchronously
6 changes: 3 additions & 3 deletions src/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1429,9 +1429,9 @@ export class Bridge {
* }
* })
*/
public registerBridgeGauges(counterFunc: () => BridgeGaugesCounts) {
this.getPrometheusMetrics().registerBridgeGauges(() => {
const counts = counterFunc();
public registerBridgeGauges(counterFunc: () => Promise<BridgeGaugesCounts>|BridgeGaugesCounts) {
this.getPrometheusMetrics().registerBridgeGauges(async () => {
const counts = await counterFunc();
if (counts.matrixGhosts !== undefined) {
counts.matrixGhosts = Object.keys(this.intents.size).length;
}
Expand Down
32 changes: 21 additions & 11 deletions src/components/prometheusmetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { AgeCounters } from "./agecounters";
import JsSdk from "matrix-js-sdk";
import { Request, Response } from "express";
import { Bridge } from "..";
type CollectorFunction = () => void;
import Logger from "./logging";
type CollectorFunction = () => Promise<void>|void;

export interface BridgeGaugesCounts {
matrixRoomConfigs?: number;
Expand Down Expand Up @@ -100,6 +101,9 @@ interface GagueOpts {
*
* @constructor
*/

const log = Logger.get('PrometheusMetrics');

export class PrometheusMetrics {
public static AgeCounters = AgeCounters;
private timers: {[name: string]: PromClient.Histogram<string>} = {};
Expand Down Expand Up @@ -173,13 +177,25 @@ export class PrometheusMetrics {
});
}

/**
* Fetch metrics from all configured collectors
*/
public async refresh () {
try {
await Promise.all(this.collectors.map((f) => f()));
}
catch (ex) {
log.warn(`Failed to refresh metrics:`, ex);
}
}

/**
* Registers some exported metrics that expose counts of various kinds of
* objects within the bridge.
* @param {BridgeGaugesCallback} counterFunc A function that when invoked
* returns the current counts of various items in the bridge.
*/
public registerBridgeGauges (counterFunc: () => BridgeGaugesCounts) {
public async registerBridgeGauges (counterFunc: () => Promise<BridgeGaugesCounts>|BridgeGaugesCounts) {
const matrixRoomsGauge = this.addGauge({
name: "matrix_configured_rooms",
help: "Current count of configured rooms by matrix room ID",
Expand Down Expand Up @@ -220,8 +236,8 @@ export class PrometheusMetrics {
labels: ["age"],
});

this.addCollector(function () {
const counts = counterFunc();
this.addCollector(async () => {
const counts = await counterFunc();

if (counts.matrixRoomConfigs) {matrixRoomsGauge.set(counts.matrixRoomConfigs);}

Expand All @@ -239,10 +255,6 @@ export class PrometheusMetrics {
});
}

public refresh () {
this.collectors.forEach((f) => f());
}

/**
* Adds a new collector function. These collector functions are run whenever
* the /metrics page is about to be generated, allowing code to update values
Expand Down Expand Up @@ -381,17 +393,15 @@ export class PrometheusMetrics {
// For now, leave this unauthenticated.
checkToken: false,
handler: async (_req: Request, res: Response) => {
this.refresh();

try {
await this.refresh();
const exposition = await this.register.metrics();

res.set("Content-Type", "text/plain");
res.send(exposition);
}
catch (e) {
res.status(500);

res.set("Content-Type", "text/plain");
res.send(e.toString());
}
Expand Down

0 comments on commit ee19602

Please sign in to comment.