Introduce tokens_http_requests and usage_tokens_duration_seconds metrics (#684)

This commit is contained in:
Kamil Kisiela 2022-11-25 09:40:38 +01:00 committed by GitHub
parent 91be8c994a
commit f9cd63724c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 2 deletions

View file

@ -1,4 +1,4 @@
import { createErrorHandler } from '@hive/service-common';
import { createErrorHandler, metrics } from '@hive/service-common';
import * as trpc from '@trpc/server';
import { inferProcedureInput, inferProcedureOutput } from '@trpc/server';
import type { FastifyLoggerInstance } from 'fastify';
@ -7,6 +7,18 @@ import { useCache } from './cache';
import { createHash } from 'crypto';
import { Lru as LruType } from 'tiny-lru';
const httpRequests = new metrics.Counter({
name: 'tokens_http_requests',
help: 'Number of http requests',
labelNames: ['path'],
});
const httpRequestDuration = new metrics.Histogram({
name: 'tokens_http_request_duration_seconds',
help: 'Duration of an http request',
labelNames: ['path'],
});
const TARGET_VALIDATION = z
.object({
targetId: z.string().nonempty(),
@ -72,6 +84,15 @@ export type Context = {
export const tokensApiRouter = trpc
.router<Context>()
.middleware(async ({ path, next }) => {
const stopTimer = httpRequestDuration.startTimer({ path });
httpRequests.inc({ path });
try {
return await next();
} finally {
stopTimer();
}
})
.query('targetTokens', {
input: TARGET_VALIDATION,
async resolve({ ctx, input }) {

View file

@ -15,6 +15,7 @@ import {
httpRequestsWithNoAccess,
collectDuration,
droppedReports,
tokensDuration,
} from './metrics';
import type { IncomingLegacyReport, IncomingReport } from './types';
import { createUsageRateLimit } from './rate-limit';
@ -96,11 +97,14 @@ async function main() {
return;
}
const stopTokensDurationTimer = tokensDuration.startTimer();
const tokenInfo = await tokens.fetch(token);
const maskedToken = maskToken(token);
if (tokens.isNotFound(tokenInfo)) {
stopTokensDurationTimer({
status: 'not_found',
});
httpRequestsWithNonExistingToken.inc();
req.log.info('Token not found (token=%s)', maskedToken);
res.status(400).send('Missing token'); // eslint-disable-line @typescript-eslint/no-floating-promises -- false positive, FastifyReply.then returns void
@ -109,12 +113,19 @@ async function main() {
// We treat collected operations as part of registry
if (tokens.isNoAccess(tokenInfo)) {
stopTokensDurationTimer({
status: 'no_access',
});
httpRequestsWithNoAccess.inc();
req.log.info('No access (token=%s)', maskedToken);
res.status(403).send('No access'); // eslint-disable-line @typescript-eslint/no-floating-promises -- false positive, FastifyReply.then returns void
return;
}
stopTokensDurationTimer({
status: 'success',
});
if (
await rateLimit?.isRateLimited({
id: tokenInfo.target,

View file

@ -10,6 +10,12 @@ export const tokenRequests = new metrics.Counter({
help: 'Number of requests to Tokens service',
});
export const tokensDuration = new metrics.Histogram({
name: 'usage_tokens_duration_seconds',
help: 'Duration of an HTTP Request to Tokens service in seconds',
labelNames: ['status'],
});
export const httpRequests = new metrics.Counter({
name: 'usage_http_requests',
help: 'Number of http requests',