Skip to content

Commit

Permalink
More OTel stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
myrotvorets-team committed Oct 26, 2023
1 parent 8f70ca5 commit 86e7796
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 10 deletions.
12 changes: 9 additions & 3 deletions src/lib/container.mts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { AwilixContainer, asFunction, asValue, createContainer } from 'awilix';
import type { NextFunction, Request, Response } from 'express';
import { type Logger, getLogger } from '@myrotvorets/otel-utils';
import { type Logger, type Tracer, getLogger, getTracer } from '@myrotvorets/otel-utils';
import { environment } from './environment.mjs';
import { MeteredGeoIPService } from '../services/meteredgeoipservice.mjs';
import { GeoIPServiceInterface } from '../services/geoipserviceinterface.mjs';

export interface Container {
geoIPService: GeoIPServiceInterface;
environment: ReturnType<typeof environment>;
tracer: Tracer;
logger: Logger;
}

Expand All @@ -34,8 +35,12 @@ function createLogger({ req }: RequestContainer): Logger {
}
/* c8 ignore stop */

function createGeoIPService({ environment }: Container): GeoIPServiceInterface {
const service = new MeteredGeoIPService();
function createTracer(): Tracer {
return getTracer();
}

function createGeoIPService({ environment, tracer }: Container): GeoIPServiceInterface {
const service = new MeteredGeoIPService({ tracer });
service.setCityDatabase(environment.GEOIP_CITY_FILE);
service.setISPDatabase(environment.GEOIP_ISP_FILE);
return service;
Expand All @@ -48,6 +53,7 @@ export function initializeContainer(): typeof container {
geoIPService: asFunction(createGeoIPService).singleton(),
environment: asFunction(createEnvironment).singleton(),
logger: asFunction(createLogger).scoped(),
tracer: asFunction(createTracer).singleton(),
});

return container;
Expand Down
6 changes: 6 additions & 0 deletions src/lib/metrics.mts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ export const ispLookupHistogram = meter.createHistogram('psbapi.geolocate.isp.du
valueType: ValueType.DOUBLE,
});

export const countryCounter = meter.createCounter('psbapi.geolocate.country', {
description: 'Number of lookups by country',
unit: '{count}',
valueType: ValueType.INT,
});

/* c8 ignore stop */
File renamed without changes.
30 changes: 27 additions & 3 deletions src/services/meteredgeoipservice.mts
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
import type { CityResponse, IspResponse } from 'maxmind';
import { type Tracer, recordErrorToSpan } from '@myrotvorets/otel-utils';
import { trace } from '@opentelemetry/api';
import { cityLookupHistogram, ispLookupHistogram } from '../lib/metrics.mjs';
import { cityLookupHistogram, countryCounter, ispLookupHistogram } from '../lib/metrics.mjs';
import { observe } from '../lib/utils.mjs';
import { GeoIPService } from './geoip.mjs';
import type { GeoCityResponse, GeoIspResponse } from './geoipserviceinterface.mjs';
import { GeoIPService } from './geoipservice.mjs';
import type { GeoCityResponse, GeoIspResponse, GeoResponse } from './geoipserviceinterface.mjs';

interface MeteredGeoIPServiceOptions {
tracer: Tracer;
}
export class MeteredGeoIPService extends GeoIPService {
private readonly _tracer: Tracer;

public constructor({ tracer }: MeteredGeoIPServiceOptions) {
super();
this._tracer = tracer;
}

public override geolocate(ip: string): GeoResponse {
return this._tracer.startActiveSpan(`geolocate ${ip}`, (span): GeoResponse => {
try {
return super.geolocate(ip);
} /* c8 ignore start */ catch (e) {
throw recordErrorToSpan(e, span);
} /* c8 ignore stop */ finally {
span.end();
}
});
}

protected override geolocateCity(ip: string): [CityResponse | null, number] {
let city: CityResponse | null = null;
let prefix = 0;
Expand Down Expand Up @@ -39,6 +62,7 @@ export class MeteredGeoIPService extends GeoIPService {
/* c8 ignore next */
?.addEvent(`GeoIP/City: Country: ${result.country ?? 'N/A'}, city: ${result.city ?? 'N/A'}`);

countryCounter.add(1, { country: result.country ?? 'ZZ' });
return result;
}

Expand Down
5 changes: 5 additions & 0 deletions test/unit/lib/container.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ describe('Container', function () {
.to.be.an('object')
.that.has.property('NODE_ENV')
.that.is.a('string');

expect(container.resolve('tracer'))
.to.be.an('object')
.that.has.property('startActiveSpan')
.that.is.a('function');
});
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TestDouble, func, matchers, replaceEsm, when } from 'testdouble';
import { type TestDouble, func, matchers, replaceEsm, when } from 'testdouble';
import { expect } from 'chai';
import type { Reader } from 'maxmind';
import type { GeoIPService } from '../../../src/services/geoip.mjs';
import type { GeoIPService } from '../../services/geoipservice.mjs';
import {
cityResponseWithCountry,
cityResponseWithRegisteredCountry,
Expand All @@ -13,7 +13,7 @@ import {
} from './helpers.mjs';

describe('GeoIPService', function () {
let geoip: typeof import('../../../src/services/geoip.mjs');
let geoip: typeof import('../../services/geoipservice.mjs');
let service: GeoIPService;
let readFileSyncMock: TestDouble<typeof import('node:fs').readFileSync>;
let constructorMock: TestDouble<(...args: unknown[]) => unknown>;
Expand Down Expand Up @@ -43,7 +43,7 @@ describe('GeoIPService', function () {

when(readFileSyncMock(matchers.isA(String) as string)).thenReturn(Buffer.from(''));

geoip = await import('../../../src/services/geoip.mjs');
geoip = await import('../../../src/services/geoipservice.mjs');
service = new geoip.GeoIPService();
});

Expand Down

0 comments on commit 86e7796

Please sign in to comment.