refactor(server): telemetry env (#13564)

This commit is contained in:
Jason Rasmussen
2024-10-17 18:04:25 -04:00
committed by GitHub
parent 23646f0d55
commit 12628b80bc
8 changed files with 108 additions and 43 deletions

View File

@@ -12,6 +12,11 @@ const resetEnv = () => {
'IMMICH_TRUSTED_PROXIES',
'IMMICH_API_METRICS_PORT',
'IMMICH_MICROSERVICES_METRICS_PORT',
'IMMICH_METRICS',
'IMMICH_API_METRICS',
'IMMICH_HOST_METRICS',
'IMMICH_IO_METRICS',
'IMMICH_JOB_METRICS',
'DB_URL',
'DB_HOSTNAME',
@@ -200,11 +205,16 @@ describe('getEnv', () => {
});
describe('telemetry', () => {
it('should return default ports', () => {
it('should have default values', () => {
const { telemetry } = getEnv();
expect(telemetry).toEqual({
apiPort: 8081,
microservicesPort: 8082,
enabled: false,
apiMetrics: false,
hostMetrics: false,
jobMetrics: false,
repoMetrics: false,
});
});
@@ -212,10 +222,35 @@ describe('getEnv', () => {
process.env.IMMICH_API_METRICS_PORT = '2001';
process.env.IMMICH_MICROSERVICES_METRICS_PORT = '2002';
const { telemetry } = getEnv();
expect(telemetry).toEqual({
expect(telemetry).toMatchObject({
apiPort: 2001,
microservicesPort: 2002,
});
});
it('should run with telemetry enabled', () => {
process.env.IMMICH_METRICS = 'true';
const { telemetry } = getEnv();
expect(telemetry).toMatchObject({
enabled: true,
apiMetrics: true,
hostMetrics: true,
jobMetrics: true,
repoMetrics: true,
});
});
it('should run with telemetry enabled and jobs disabled', () => {
process.env.IMMICH_METRICS = 'true';
process.env.IMMICH_JOB_METRICS = 'false';
const { telemetry } = getEnv();
expect(telemetry).toMatchObject({
enabled: true,
apiMetrics: true,
hostMetrics: true,
jobMetrics: false,
repoMetrics: true,
});
});
});
});

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { join } from 'node:path';
import { citiesFile } from 'src/constants';
import { citiesFile, excludePaths } from 'src/constants';
import { ImmichEnvironment, ImmichWorker, LogLevel } from 'src/enum';
import { EnvData, IConfigRepository } from 'src/interfaces/config.interface';
import { DatabaseExtension } from 'src/interfaces/database.interface';
@@ -30,6 +30,8 @@ const asSet = (value: string | undefined, defaults: ImmichWorker[]) => {
return new Set(values.length === 0 ? defaults : (values as ImmichWorker[]));
};
const parseBoolean = (value: string | undefined, defaultValue: boolean) => (value ? value === 'true' : defaultValue);
const getEnv = (): EnvData => {
const included = asSet(process.env.IMMICH_WORKERS_INCLUDE, [ImmichWorker.API, ImmichWorker.MICROSERVICES]);
const excluded = asSet(process.env.IMMICH_WORKERS_EXCLUDE, []);
@@ -66,6 +68,16 @@ const getEnv = (): EnvData => {
}
}
const globalEnabled = parseBoolean(process.env.IMMICH_METRICS, false);
const hostMetrics = parseBoolean(process.env.IMMICH_HOST_METRICS, globalEnabled);
const apiMetrics = parseBoolean(process.env.IMMICH_API_METRICS, globalEnabled);
const repoMetrics = parseBoolean(process.env.IMMICH_IO_METRICS, globalEnabled);
const jobMetrics = parseBoolean(process.env.IMMICH_JOB_METRICS, globalEnabled);
const telemetryEnabled = globalEnabled || hostMetrics || apiMetrics || repoMetrics || jobMetrics;
if (!telemetryEnabled && process.env.OTEL_SDK_DISABLED === undefined) {
process.env.OTEL_SDK_DISABLED = 'true';
}
return {
host: process.env.IMMICH_HOST,
port: Number(process.env.IMMICH_PORT) || 2283,
@@ -124,6 +136,16 @@ const getEnv = (): EnvData => {
.filter(Boolean),
},
otel: {
metrics: {
hostMetrics,
apiMetrics: {
enable: apiMetrics,
ignoreRoutes: excludePaths,
},
},
},
redis: redisConfig,
resourcePaths: {
@@ -148,6 +170,11 @@ const getEnv = (): EnvData => {
telemetry: {
apiPort: Number(process.env.IMMICH_API_METRICS_PORT || '') || 8081,
microservicesPort: Number(process.env.IMMICH_MICROSERVICES_METRICS_PORT || '') || 8082,
enabled: telemetryEnabled,
hostMetrics,
apiMetrics,
repoMetrics,
jobMetrics,
},
workers,

View File

@@ -1,11 +1,12 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { MetricOptions } from '@opentelemetry/api';
import { MetricService } from 'nestjs-otel';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { IMetricGroupRepository, IMetricRepository, MetricGroupOptions } from 'src/interfaces/metric.interface';
import { apiMetrics, hostMetrics, jobMetrics, repoMetrics } from 'src/utils/instrumentation';
class MetricGroupRepository implements IMetricGroupRepository {
private enabled = false;
constructor(private metricService: MetricService) {}
addToCounter(name: string, value: number, options?: MetricOptions): void {
@@ -39,10 +40,11 @@ export class MetricRepository implements IMetricRepository {
jobs: MetricGroupRepository;
repo: MetricGroupRepository;
constructor(metricService: MetricService) {
this.api = new MetricGroupRepository(metricService).configure({ enabled: apiMetrics });
this.host = new MetricGroupRepository(metricService).configure({ enabled: hostMetrics });
this.jobs = new MetricGroupRepository(metricService).configure({ enabled: jobMetrics });
this.repo = new MetricGroupRepository(metricService).configure({ enabled: repoMetrics });
constructor(metricService: MetricService, @Inject(IConfigRepository) configRepository: IConfigRepository) {
const { telemetry } = configRepository.getEnv();
this.api = new MetricGroupRepository(metricService).configure({ enabled: telemetry.apiMetrics });
this.host = new MetricGroupRepository(metricService).configure({ enabled: telemetry.hostMetrics });
this.jobs = new MetricGroupRepository(metricService).configure({ enabled: telemetry.jobMetrics });
this.repo = new MetricGroupRepository(metricService).configure({ enabled: telemetry.repoMetrics });
}
}