Skip to content

Commit

Permalink
task(admin-server): Fix startup times and some refactor
Browse files Browse the repository at this point in the history
Because:
- We want to improve startup performance of admin-server
- We determined using the @sentry/node package in the admin-server was source of slowdown
- Using @sentry/nestjs made a big improvement in startup time.

This Commit:
- Switches to using @sentry/nestjs integration for admin-server
- Refactors libs/sentry into three distinct contexts libs/sentry-nestjs, libs/sentry-node, libs/sentry-browser, and libs/sentry-utils
- Extracts common functions to libs/sentry-utils so they can be reused.
  • Loading branch information
dschom committed Oct 30, 2024
1 parent fcb2242 commit 14b9341
Show file tree
Hide file tree
Showing 119 changed files with 4,951 additions and 1,038 deletions.
4 changes: 2 additions & 2 deletions libs/shared/l10n/src/lib/l10n.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { DEFAULT_LOCALE, EN_GB_LOCALES } from './l10n.constants';
*
*/
export function parseAcceptLanguage(
acceptLanguage: string,
acceptLanguage?: string,
supportedLanguages?: string[]
) {
if (!supportedLanguages) {
Expand Down Expand Up @@ -144,7 +144,7 @@ export function getLocaleFromRequest(
* @returns The best fitting locale
*/
export function determineLocale(
acceptLanguage: string,
acceptLanguage?: string,
supportedLanguages?: string[]
) {
// Returns languages in order of precedence, so we can just grab the first one.
Expand Down
2 changes: 1 addition & 1 deletion libs/shared/log/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

export { logger } from './lib/logging';
export * from './lib/logging';
export { monkeyPatchServerLogging } from './lib/monkey-patch';
export { LoggingModule, LOGGER_PROVIDER } from './lib/nest/logging.module';
export type { Logger } from './lib/nest/logging.module';
7 changes: 7 additions & 0 deletions libs/shared/log/src/lib/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@ export const logger = createLogger({
exitOnError: true,
...exceptionHandling,
} as LoggerOptions);

export type ILogger = {
error: (type: string, data: any) => void;
debug: (type: string, data: any) => void;
info: (type: string, data: any) => void;
warn: (type: string, data: any) => void;
};
18 changes: 18 additions & 0 deletions libs/shared/otel/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
11 changes: 11 additions & 0 deletions libs/shared/otel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# shared-otel

This library was generated with [Nx](https://nx.dev).

## Building

Run `nx build shared-otel` to build the library.

## Running unit tests

Run `nx test shared-otel` to execute the unit tests via [Jest](https://jestjs.io).
11 changes: 11 additions & 0 deletions libs/shared/otel/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: 'shared-otel',
preset: '../../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../../coverage/libs/shared/otel',
};
4 changes: 4 additions & 0 deletions libs/shared/otel/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@fxa/shared/otel",
"version": "0.0.1"
}
29 changes: 29 additions & 0 deletions libs/shared/otel/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "shared-otel",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/shared/otel/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/shared/otel",
"main": "libs/shared/otel/src/index.ts",
"tsConfig": "libs/shared/otel/tsconfig.lib.json",
"assets": ["libs/shared/otel/*.md"],
"generatePackageJson": true,
"declaration": true,
"platform": "node"
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/shared/otel/jest.config.ts"
}
}
}
}
7 changes: 7 additions & 0 deletions libs/shared/otel/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

export * from './lib/config';
export * from './lib/pii-filters';
export * from './lib/node-tracing';
135 changes: 135 additions & 0 deletions libs/shared/otel/src/lib/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

export const logType = 'fxa-otel';
/**
* Options for configuring tracing.
*/
export type TracingOpts = {
batchProcessor: boolean;
clientName: string;
corsUrls: string;
filterPii: boolean;
sampleRate: number;
serviceName: string;

console?: {
enabled: boolean;
};
gcp?: {
enabled: boolean;
};
otel?: {
enabled: boolean;
url: string;
concurrencyLimit: number;
};
};

/** Default convict config for node tracing */
export const tracingConfig = {
clientName: {
default: '',
doc: 'The name of client being traced.',
env: 'TRACING_CLIENT_NAME',
format: String,
},
batchProcessor: {
default: true,
doc: 'Indicates if batch processing should be used. Batch processing is better for production environments.',
env: 'TRACING_BATCH_PROCESSING',
format: Boolean,
},
corsUrls: {
default: 'http://localhost:\\d*/',
doc: 'A regex to allow tracing of cors requests',
env: 'TRACING_CORS_URLS',
format: String,
},
filterPii: {
default: true,
doc: 'Enables filtering PII in Console traces.',
env: 'TRACING_FILTER_PII',
format: Boolean,
},
sampleRate: {
default: 0,
doc: 'A number between 0 and 1 that indicates the rate at which to sample. 1 will capture all traces. .5 would capture half the traces, and 0 would capture no traces.',
env: 'TRACING_SAMPLE_RATE',
format: Number,
},
serviceName: {
default: '',
doc: 'The name of service being traced.',
env: 'TRACING_SERVICE_NAME',
format: String,
},
console: {
enabled: {
default: false,
doc: 'Trace report to the console',
env: 'TRACING_CONSOLE_EXPORTER_ENABLED',
format: Boolean,
},
},
gcp: {
enabled: {
default: false,
doc: 'Traces report to google cloud tracing. This should be turned on in the wild, but is discouraged for local development.',
env: 'TRACING_GCP_EXPORTER_ENABLED',
format: Boolean,
},
},
otel: {
enabled: {
default: false,
doc: 'Traces report to the otel. This is only applicable for local development.',
env: 'TRACING_OTEL_EXPORTER_ENABLED',
format: Boolean,
},
url: {
default: 'http://localhost:4318/v1/traces',
doc: 'Open telemetry collector url',
env: 'TRACING_OTEL_URL',
format: String,
},
concurrencyLimit: {
default: 100,
doc: 'Max amount of concurrency',
env: 'TRACING_OTEL_CONCURRENCY_LIMIT',
format: Number,
},
},
};

export function checkServiceName(opts: Pick<TracingOpts, 'serviceName'>) {
if (!opts.serviceName) {
throw new Error('Missing config. serviceName must be defined!');
}
}

export function checkSampleRate(opts: Pick<TracingOpts, 'sampleRate'>) {
if (
opts.sampleRate == null ||
Number.isNaN(opts.sampleRate) ||
opts.sampleRate < 0 ||
opts.sampleRate > 1
) {
throw new Error(
`Invalid config. sampleRate must be a number between 0 and 1, but was ${opts.sampleRate}.`
);
}
}

export function checkClientName(opts: Pick<TracingOpts, 'clientName'>) {
if (!opts.clientName) {
throw new Error('Missing config. clientName must be defined!');
}
}

export function someModesEnabled(
opts: Pick<TracingOpts, 'otel' | 'gcp' | 'console'>
) {
return opts.otel?.enabled || opts.gcp?.enabled || opts.console?.enabled;
}
25 changes: 25 additions & 0 deletions libs/shared/otel/src/lib/exporters/exporters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { TracingOpts } from '../config';
import {
NodeTracerProvider,
BatchSpanProcessor,
SimpleSpanProcessor,
SpanExporter,
} from '@opentelemetry/sdk-trace-node';

export function addExporter(
opts: TracingOpts,
provider: NodeTracerProvider,
exporter: SpanExporter
) {
const processor = opts.batchProcessor
? new BatchSpanProcessor(exporter)
: new SimpleSpanProcessor(exporter);
provider.addSpanProcessor(processor);

provider.addSpanProcessor(processor);
return processor;
}
48 changes: 48 additions & 0 deletions libs/shared/otel/src/lib/exporters/fxa-console.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { ExportResult } from '@opentelemetry/core';
import {
BasicTracerProvider,
ConsoleSpanExporter,
ReadableSpan,
} from '@opentelemetry/sdk-trace-node';
import { logType, TracingOpts } from '../config';
import { TracingPiiFilter } from '../pii-filters';
import { addExporter } from './exporters';
import { checkDuration } from './util';
import { ILogger } from '@fxa/shared/log';

/** Console Exporter exporter customized for FxA */
export class FxaConsoleSpanExporter extends ConsoleSpanExporter {
constructor(protected readonly filter?: TracingPiiFilter) {
super();
}

override export(
spans: ReadableSpan[],
resultCallback: (result: ExportResult) => void
) {
spans.forEach((x) => {
checkDuration(x);
this.filter?.filter(x);
});
return super.export(spans, resultCallback);
}
}

export function addConsoleExporter(
opts: TracingOpts,
provider: BasicTracerProvider,
filter?: TracingPiiFilter,
logger?: ILogger
) {
if (!opts.console?.enabled) {
return;
}
logger?.debug(logType, 'Adding Console Exporter');
const exporter = new FxaConsoleSpanExporter(filter);
addExporter(opts, provider, exporter);
return exporter;
}
56 changes: 56 additions & 0 deletions libs/shared/otel/src/lib/exporters/fxa-gcp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import {
TraceExporter as GcpTraceExporter,
TraceExporterOptions as GcpTraceExporterOptions,
} from '@google-cloud/opentelemetry-cloud-trace-exporter';
import { ExportResult } from '@opentelemetry/core';
import {
BasicTracerProvider,
ReadableSpan,
} from '@opentelemetry/sdk-trace-node';
import { TracingOpts, logType } from '../config';
import { TracingPiiFilter } from '../pii-filters';
import { addExporter } from './exporters';
import { checkDuration } from './util';
import { ILogger } from '@fxa/shared/log';

/** Gcp exporter customized for FxA */

export class FxaGcpTraceExporter extends GcpTraceExporter {
constructor(
protected readonly filter?: TracingPiiFilter,
config?: GcpTraceExporterOptions
) {
super(config);
}

override export(
spans: ReadableSpan[],
resultCallback: (result: ExportResult) => void
) {
spans.forEach((x) => {
checkDuration(x);
this.filter?.filter(x);
});
return super.export(spans, resultCallback);
}
}

export function addGcpTraceExporter(
opts: TracingOpts,
provider: BasicTracerProvider,
filter?: TracingPiiFilter,
logger?: ILogger
) {
if (!opts.gcp?.enabled) {
return;
}

logger?.debug(logType, { msg: 'Adding Gcp Trace Exporter' });
const exporter = new FxaGcpTraceExporter(filter);
addExporter(opts, provider, exporter);
return exporter;
}
Loading

0 comments on commit 14b9341

Please sign in to comment.