feat(api): metrics for Spotify API http requests

This will help evaluate how much we are being rate limited, and on what
routes it happens most.
This commit is contained in:
Julian Tölle 2022-06-29 19:58:01 +02:00
parent 85c31705ef
commit 41dfae3c50
7 changed files with 229 additions and 3 deletions

View file

@ -0,0 +1,84 @@
import {
AxiosFulfilledInterceptor,
AxiosInterceptor,
AxiosResponseCustomConfig,
} from "@narando/nest-axios-interceptor";
import { HttpService } from "@nestjs/axios";
import { Injectable, Logger } from "@nestjs/common";
import { Counter, Histogram } from "@opentelemetry/api-metrics";
import type { AxiosRequestConfig } from "axios";
import { MetricService } from "nestjs-otel";
import { UrlValueParserService } from "../../../open-telemetry/url-value-parser.service";
const SPOTIFY_API_METRICS_CONFIG_KEY = Symbol("kSpotifyApiMetricsInterceptor");
// Merging our custom properties with the base config
interface SpotifyApiMetricsConfig extends AxiosRequestConfig {
[SPOTIFY_API_METRICS_CONFIG_KEY]: {
startTime: number;
};
}
@Injectable()
export class MetricsInterceptor extends AxiosInterceptor<SpotifyApiMetricsConfig> {
private readonly logger = new Logger(this.constructor.name);
responseCounter: Counter;
requestHistogram: Histogram;
constructor(
httpService: HttpService,
metricService: MetricService,
private readonly urlValueParserService: UrlValueParserService
) {
super(httpService);
this.responseCounter = metricService.getCounter(
"listory_spotify_api_http_response",
{ description: "Total number of HTTP responses from Spotify API" }
);
this.requestHistogram = metricService.getHistogram(
"listory_spotify_api_http_request_duration_seconds",
{
description:
"HTTP latency value recorder in seconds for requests made to Spotify API",
boundaries: [0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
}
);
}
protected requestFulfilled(): AxiosFulfilledInterceptor<SpotifyApiMetricsConfig> {
return (config) => {
config[SPOTIFY_API_METRICS_CONFIG_KEY] = {
startTime: new Date().getTime(),
};
return config;
};
}
responseFulfilled(): AxiosFulfilledInterceptor<
AxiosResponseCustomConfig<SpotifyApiMetricsConfig>
> {
return (response) => {
const startTime =
response.config[SPOTIFY_API_METRICS_CONFIG_KEY].startTime;
const endTime = new Date().getTime();
const responseTimeSeconds = (endTime - startTime) / 1000;
const metricLabels = {
method: response.config.method.toUpperCase(),
status: response.status.toString(),
path: this.urlValueParserService.replacePathValues(
response.config.url,
"<id>"
),
};
this.requestHistogram.record(responseTimeSeconds, metricLabels);
this.responseCounter.add(1, metricLabels);
return response;
};
}
}

View file

@ -1,6 +1,7 @@
import { HttpModule } from "@nestjs/axios";
import { Module } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { MetricsInterceptor } from "./metrics.axios-interceptor";
import { SpotifyApiService } from "./spotify-api.service";
@Module({
@ -13,7 +14,7 @@ import { SpotifyApiService } from "./spotify-api.service";
inject: [ConfigService],
}),
],
providers: [SpotifyApiService],
providers: [SpotifyApiService, MetricsInterceptor],
exports: [SpotifyApiService],
})
export class SpotifyApiModule {}