use a fasthttp request for metrics push
This commit is contained in:
parent
e31451bae5
commit
c424476f55
@ -3,6 +3,7 @@ import { PrometheusContentType, Registry, Pushgateway, Summary, Counter, registe
|
||||
import { DoormanLambdaContext } from "./DoormanHandlerContext";
|
||||
import { shouldBlockRequest } from "../utils/blockUserAgent";
|
||||
import { RequestOptions } from "https";
|
||||
import { FastHttpPushgateway } from "../metrics/FastHttpPromGateway";
|
||||
|
||||
export type BaseEvent = { request: { cookies: {}; headers: {}; }; }
|
||||
|
||||
@ -44,7 +45,7 @@ export function withMetrics<T extends DoormanLambdaContext, U extends BaseEvent>
|
||||
},
|
||||
};
|
||||
|
||||
const pushGateway = new Pushgateway(context.PUSHGATEWAY_URL, requestOptions, metricsRegistry);
|
||||
const pushGateway = new FastHttpPushgateway(context.PUSHGATEWAY_URL, requestOptions, metricsRegistry);
|
||||
|
||||
metricsRegistry.registerMetric(new Summary({
|
||||
name: CommonMetrics.RUNTIME,
|
||||
@ -111,7 +112,7 @@ export function withMetrics<T extends DoormanLambdaContext, U extends BaseEvent>
|
||||
console.log(`[CommonHandler] there is ${remainingTime} ms left to send metrics`);
|
||||
|
||||
let metricsTimeout = setTimeout(() => {
|
||||
console.error("[CommonHandler] cutting it too close, abandoning metrics");
|
||||
console.log("[CommonHandler] cutting it too close, abandoning metrics");
|
||||
callback(...result);
|
||||
}, remainingTime - 250);
|
||||
|
||||
@ -127,10 +128,8 @@ export function withMetrics<T extends DoormanLambdaContext, U extends BaseEvent>
|
||||
});
|
||||
console.log("[CommonHandler] pushed metrics successfully");
|
||||
} catch (e: any) {
|
||||
console.error("[CommonHandler] failed to push metrics, quietly discarding them", e);
|
||||
console.log("[CommonHandler] failed to push metrics, quietly discarding them", e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
clearTimeout(metricsTimeout);
|
||||
callback(...result);
|
||||
|
||||
90
packages/doorman-api/src/metrics/FastHttpPromGateway.ts
Normal file
90
packages/doorman-api/src/metrics/FastHttpPromGateway.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { Pushgateway, Registry, RegistryContentType } from "prom-client";
|
||||
import url from "url";
|
||||
import http from "http";
|
||||
import https from "https";
|
||||
import { gzipSync } from "zlib";
|
||||
|
||||
// copied mostly from pushgateway.js implementation. Just swapping out the http call to not await a response
|
||||
|
||||
export class FastHttpPushgateway<T extends RegistryContentType> extends Pushgateway<T> {
|
||||
constructor(url: string, options?: any, registry?: Registry<T>) {
|
||||
super(url, options, registry);
|
||||
}
|
||||
|
||||
override push(params: Pushgateway.Parameters): Promise<{ resp?: unknown; body?: unknown; }> {
|
||||
let method = "PUT";
|
||||
let job = params.jobName;
|
||||
let groupings = params.groupings;
|
||||
|
||||
// @ts-ignore
|
||||
let gatewayUrl: string = this.gatewayUrl;
|
||||
// @ts-ignore
|
||||
let requestOptions: any = this.requestOptions;
|
||||
|
||||
// @ts-ignore
|
||||
let registry: Registry = this.registry;
|
||||
|
||||
// `URL` first added in v6.13.0
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
const gatewayUrlParsed = url.parse(gatewayUrl);
|
||||
const gatewayUrlPath =
|
||||
gatewayUrlParsed.pathname && gatewayUrlParsed.pathname !== '/'
|
||||
? gatewayUrlParsed.pathname
|
||||
: '';
|
||||
const jobPath = job
|
||||
? `/job/${encodeURIComponent(job)}${generateGroupings(groupings)}`
|
||||
: '';
|
||||
const path = `${gatewayUrlPath}/metrics${jobPath}`;
|
||||
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
const target = url.resolve(gatewayUrl, path);
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
const requestParams = url.parse(target);
|
||||
const httpModule = isHttps(requestParams.href) ? https : http;
|
||||
const options = Object.assign(requestParams, requestOptions, {
|
||||
method,
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (method === 'DELETE' && options.headers) {
|
||||
delete options.headers['Content-Encoding'];
|
||||
}
|
||||
const req = httpModule.request(options);
|
||||
|
||||
// write metrics
|
||||
registry
|
||||
.metrics()
|
||||
.then(metrics => {
|
||||
if (
|
||||
options.headers &&
|
||||
options.headers['Content-Encoding'] === 'gzip'
|
||||
) {
|
||||
metrics = gzipSync(metrics) as any;
|
||||
}
|
||||
|
||||
// write metrics, and once thats done, end req. Don't wait for response
|
||||
req.write(metrics, () => {
|
||||
req.end(() => {
|
||||
resolve({});
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function generateGroupings(groupings: any) {
|
||||
if (!groupings) {
|
||||
return '';
|
||||
}
|
||||
return Object.keys(groupings)
|
||||
.map(
|
||||
key =>
|
||||
`/${encodeURIComponent(key)}/${encodeURIComponent(groupings[key])}`,
|
||||
)
|
||||
.join('');
|
||||
}
|
||||
|
||||
function isHttps(href: string) {
|
||||
return href.search(/^https/) !== -1;
|
||||
}
|
||||
@ -135,11 +135,11 @@ export const handler: ServerlessFunctionSignature<TwilioContext, BuzzerDialEvent
|
||||
.inc({ door: config.door }, 1);
|
||||
|
||||
const twiml = dialFallbackTwiml(config);
|
||||
console.error(
|
||||
console.log(
|
||||
invokeId, "UngracefulFallbackPromise: Cutting it too close to timeout! Skipping notifying users and calling fallback"
|
||||
);
|
||||
resolve(twiml);
|
||||
}, 9500));
|
||||
}, 9000));
|
||||
});
|
||||
|
||||
const twiml = await Promise.race([unlockPromise, gracefulFallbackPromise, ungracefulFallbackPromise]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user