Revert "fix(server): wrong usage of optl (#6714)"

This reverts commit 4868f6e611.
This commit is contained in:
forehalo
2024-07-19 11:31:01 +08:00
parent 585003640f
commit 90c00b6db9
11 changed files with 70 additions and 182 deletions

View File

@@ -8,16 +8,15 @@
"run-test": "./scripts/run-test.ts" "run-test": "./scripts/run-test.ts"
}, },
"scripts": { "scripts": {
"run:script": "node --import ./scripts/register.js",
"build": "tsc", "build": "tsc",
"start": "yarn run:script ./src/index.ts", "start": "node --loader ts-node/esm/transpile-only.mjs ./src/index.ts",
"dev": "nodemon ./src/index.ts", "dev": "nodemon ./src/index.ts",
"test": "ava --concurrency 1 --serial", "test": "ava --concurrency 1 --serial",
"test:coverage": "c8 ava --concurrency 1 --serial", "test:coverage": "c8 ava --concurrency 1 --serial",
"postinstall": "prisma generate", "postinstall": "prisma generate",
"data-migration": "yarn run:script ./src/data/index.ts", "data-migration": "node --loader ts-node/esm/transpile-only.mjs ./src/data/index.ts",
"predeploy": "yarn prisma migrate deploy && yarn run:script ./dist/data/index.js run", "predeploy": "yarn prisma migrate deploy && node --import ./scripts/register.js ./dist/data/index.js run",
"db:upgrade": "yarn prisma migrate deploy && yarn data-migration run" "predeploy:ts": "yarn prisma migrate deploy && node --loader ts-node/esm/transpile-only.mjs ./src/data/index.ts run"
}, },
"dependencies": { "dependencies": {
"@apollo/server": "^4.10.2", "@apollo/server": "^4.10.2",
@@ -43,8 +42,8 @@
"@node-rs/jsonwebtoken": "^0.5.2", "@node-rs/jsonwebtoken": "^0.5.2",
"@opentelemetry/api": "^1.9.0", "@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^1.25.0", "@opentelemetry/core": "^1.25.0",
"@opentelemetry/exporter-metrics-otlp-proto": "^0.52.0", "@opentelemetry/exporter-prometheus": "^0.52.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.52.0", "@opentelemetry/exporter-zipkin": "^1.25.0",
"@opentelemetry/host-metrics": "^0.35.2", "@opentelemetry/host-metrics": "^0.35.2",
"@opentelemetry/instrumentation": "^0.52.0", "@opentelemetry/instrumentation": "^0.52.0",
"@opentelemetry/instrumentation-graphql": "^0.42.0", "@opentelemetry/instrumentation-graphql": "^0.42.0",
@@ -166,8 +165,9 @@
"exec": "node", "exec": "node",
"script": "./src/index.ts", "script": "./src/index.ts",
"nodeArgs": [ "nodeArgs": [
"--import", "--loader",
"./scripts/register.js" "ts-node/esm.mjs",
"--es-module-specifier-resolution=node"
], ],
"ignore": [ "ignore": [
"**/__tests__/**", "**/__tests__/**",

View File

@@ -1,32 +1,11 @@
import * as otel from '@opentelemetry/instrumentation/hook.mjs'; import { create, createEsmHooks } from 'ts-node';
import { createEsmHooks, register } from 'ts-node';
const service = register({ const service = create({
experimentalSpecifierResolution: 'node', experimentalSpecifierResolution: 'node',
transpileOnly: true, transpileOnly: true,
logError: true, logError: true,
skipProject: true,
}); });
const hooks = createEsmHooks(service);
/** export const resolve = hooks.resolve;
* @type {import('ts-node').NodeLoaderHooksAPI2}
*/
const ts = createEsmHooks(service);
/**
* @type {import('ts-node').NodeLoaderHooksAPI2.ResolveHook}
*/
export const resolve = (specifier, context, defaultResolver) => {
return ts.resolve(specifier, context, (s, c) => {
return otel.resolve(s, c, defaultResolver);
});
};
/**
* @type {import('ts-node').NodeLoaderHooksAPI2.LoadHook}
*/
export const load = async (url, context, defaultLoader) => {
return await otel.load(url, context, (u, c) => {
return ts.load(u, c, defaultLoader);
});
};

View File

@@ -3,13 +3,9 @@ import '../prelude';
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { CommandFactory } from 'nest-commander'; import { CommandFactory } from 'nest-commander';
import { registerInstrumentations } from '../fundamentals/metrics';
async function bootstrap() { async function bootstrap() {
AFFiNE.metrics.enabled = false; AFFiNE.metrics.enabled = false;
AFFiNE.doc.manager.enableUpdateAutoMerging = false; AFFiNE.doc.manager.enableUpdateAutoMerging = false;
registerInstrumentations();
const { CliAppModule } = await import('./app'); const { CliAppModule } = await import('./app');
await CommandFactory.run(CliAppModule, new Logger()).catch(e => { await CommandFactory.run(CliAppModule, new Logger()).catch(e => {
console.error(e); console.error(e);

View File

@@ -9,6 +9,9 @@ export class UnamedAccount1703756315970 {
const users = await db.$queryRaw< const users = await db.$queryRaw<
User[] User[]
>`SELECT * FROM users WHERE name ~ E'^[\\s\\u2000-\\u200F]*$';`; >`SELECT * FROM users WHERE name ~ E'^[\\s\\u2000-\\u200F]*$';`;
console.log(
`renaming ${users.map(({ email }) => email).join('|')} users`
);
await Promise.all( await Promise.all(
users.map(({ id, email }) => users.map(({ id, email }) =>

View File

@@ -50,7 +50,6 @@ export class MetricsModule implements OnModuleInit, OnModuleDestroy {
} }
} }
export { registerInstrumentations } from './instrumentations';
export * from './metrics'; export * from './metrics';
export * from './utils'; export * from './utils';
export { OpentelemetryFactory }; export { OpentelemetryFactory };

View File

@@ -1,32 +0,0 @@
import { Instrumentation } from '@opentelemetry/instrumentation';
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';
import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core';
import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io';
import prismaInstrument from '@prisma/instrumentation';
const { PrismaInstrumentation } = prismaInstrument;
let instrumentations: Instrumentation[] = [];
export function registerInstrumentations(): void {
if (AFFiNE.metrics.enabled) {
instrumentations = [
new NestInstrumentation(),
new IORedisInstrumentation(),
new SocketIoInstrumentation({ traceReserved: true }),
new GraphQLInstrumentation({
mergeItems: true,
ignoreTrivialResolveSpans: true,
depth: 10,
}),
new HttpInstrumentation(),
new PrismaInstrumentation({ middleware: false }),
];
}
}
export function getRegisteredInstrumentations(): Instrumentation[] {
return instrumentations;
}

View File

@@ -1,82 +1,52 @@
import { Attributes, metrics } from '@opentelemetry/api'; import { OnModuleDestroy } from '@nestjs/common';
import { metrics } from '@opentelemetry/api';
import { import {
CompositePropagator, CompositePropagator,
W3CBaggagePropagator, W3CBaggagePropagator,
W3CTraceContextPropagator, W3CTraceContextPropagator,
} from '@opentelemetry/core'; } from '@opentelemetry/core';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'; import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'; import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
import { HostMetrics } from '@opentelemetry/host-metrics'; import { HostMetrics } from '@opentelemetry/host-metrics';
import { Instrumentation } from '@opentelemetry/instrumentation'; import { Instrumentation } from '@opentelemetry/instrumentation';
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';
import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core';
import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io';
import { Resource } from '@opentelemetry/resources'; import { Resource } from '@opentelemetry/resources';
import type { MeterProvider } from '@opentelemetry/sdk-metrics'; import type { MeterProvider } from '@opentelemetry/sdk-metrics';
import { import { MetricProducer, MetricReader } from '@opentelemetry/sdk-metrics';
MetricProducer,
MetricReader,
PeriodicExportingMetricReader,
} from '@opentelemetry/sdk-metrics';
import { NodeSDK } from '@opentelemetry/sdk-node'; import { NodeSDK } from '@opentelemetry/sdk-node';
import { import {
BatchSpanProcessor,
SpanExporter, SpanExporter,
TraceIdRatioBasedSampler, TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace-node'; } from '@opentelemetry/sdk-trace-node';
import { import {
SEMRESATTRS_K8S_CLUSTER_NAME,
SEMRESATTRS_K8S_NAMESPACE_NAME, SEMRESATTRS_K8S_NAMESPACE_NAME,
SEMRESATTRS_K8S_POD_NAME, SEMRESATTRS_SERVICE_NAME,
SEMRESATTRS_SERVICE_VERSION, SEMRESATTRS_SERVICE_VERSION,
} from '@opentelemetry/semantic-conventions'; } from '@opentelemetry/semantic-conventions';
import prismaInstrument from '@prisma/instrumentation';
import { getRegisteredInstrumentations } from './instrumentations';
import { PrismaMetricProducer } from './prisma'; import { PrismaMetricProducer } from './prisma';
function withBuiltinAttributesMetricReader( const { PrismaInstrumentation } = prismaInstrument;
reader: MetricReader,
attrs: Attributes
) {
const collect = reader.collect;
reader.collect = async options => {
const result = await collect.call(reader, options);
result.resourceMetrics.scopeMetrics.forEach(metrics => {
metrics.metrics.forEach(metric => {
metric.dataPoints.forEach(dataPoint => {
// @ts-expect-error allow
dataPoint.attributes = Object.assign({}, attrs, dataPoint.attributes);
});
});
});
return result;
};
return reader;
}
function withBuiltinAttributesSpanExporter(
exporter: SpanExporter,
attrs: Attributes
) {
const exportSpans = exporter.export;
exporter.export = (spans, callback) => {
spans.forEach(span => {
// patch span attributes
// @ts-expect-error allow
span.attributes = Object.assign({}, attrs, span.attributes);
});
return exportSpans.call(exporter, spans, callback);
};
return exporter;
}
export abstract class OpentelemetryFactory { export abstract class OpentelemetryFactory {
abstract getMetricReader(): MetricReader; abstract getMetricReader(): MetricReader;
abstract getSpanExporter(): SpanExporter; abstract getSpanExporter(): SpanExporter;
getInstractions(): Instrumentation[] { getInstractions(): Instrumentation[] {
return getRegisteredInstrumentations(); return [
new NestInstrumentation(),
new IORedisInstrumentation(),
new SocketIoInstrumentation({ traceReserved: true }),
new GraphQLInstrumentation({ mergeItems: true }),
new HttpInstrumentation(),
new PrismaInstrumentation(),
];
} }
getMetricsProducers(): MetricProducer[] { getMetricsProducers(): MetricProducer[] {
@@ -85,32 +55,20 @@ export abstract class OpentelemetryFactory {
getResource() { getResource() {
return new Resource({ return new Resource({
[SEMRESATTRS_K8S_CLUSTER_NAME]: AFFiNE.flavor.type,
[SEMRESATTRS_K8S_NAMESPACE_NAME]: AFFiNE.AFFINE_ENV, [SEMRESATTRS_K8S_NAMESPACE_NAME]: AFFiNE.AFFINE_ENV,
[SEMRESATTRS_K8S_POD_NAME]: process.env.HOSTNAME ?? process.env.HOST, [SEMRESATTRS_SERVICE_NAME]: AFFiNE.flavor.type,
[SEMRESATTRS_SERVICE_VERSION]: AFFiNE.version,
}); });
} }
getBuiltinAttributes(): Attributes {
return {
[SEMRESATTRS_SERVICE_VERSION]: AFFiNE.version,
};
}
create() { create() {
const builtinAttributes = this.getBuiltinAttributes(); const traceExporter = this.getSpanExporter();
return new NodeSDK({ return new NodeSDK({
resource: this.getResource(), resource: this.getResource(),
sampler: new TraceIdRatioBasedSampler(0.1), sampler: new TraceIdRatioBasedSampler(0.1),
traceExporter: withBuiltinAttributesSpanExporter( traceExporter,
this.getSpanExporter(), metricReader: this.getMetricReader(),
builtinAttributes spanProcessor: new BatchSpanProcessor(traceExporter),
),
metricReader: withBuiltinAttributesMetricReader(
this.getMetricReader(),
builtinAttributes
),
textMapPropagator: new CompositePropagator({ textMapPropagator: new CompositePropagator({
propagators: [ propagators: [
new W3CBaggagePropagator(), new W3CBaggagePropagator(),
@@ -123,19 +81,24 @@ export abstract class OpentelemetryFactory {
} }
} }
export class LocalOpentelemetryFactory extends OpentelemetryFactory { export class LocalOpentelemetryFactory
override getMetricReader() { extends OpentelemetryFactory
return new PeriodicExportingMetricReader({ implements OnModuleDestroy
// requires jeager service running in 'http://localhost:4318' {
// with metrics feature enabled. private readonly metricsExporter = new PrometheusExporter({
// see https://www.jaegertracing.io/docs/1.56/spm metricProducers: this.getMetricsProducers(),
exporter: new OTLPMetricExporter(), });
});
async onModuleDestroy() {
await this.metricsExporter.shutdown();
} }
override getSpanExporter() { override getMetricReader(): MetricReader {
// requires jeager service running in 'http://localhost:4318' return this.metricsExporter;
return new OTLPTraceExporter(); }
override getSpanExporter(): SpanExporter {
return new ZipkinExporter();
} }
} }

View File

@@ -6,9 +6,7 @@ import { omit } from 'lodash-es';
import { createApp } from './app'; import { createApp } from './app';
import { URLHelper } from './fundamentals'; import { URLHelper } from './fundamentals';
import { registerInstrumentations } from './fundamentals/metrics';
registerInstrumentations();
const app = await createApp(); const app = await createApp();
const listeningHost = AFFiNE.deploy ? '0.0.0.0' : 'localhost'; const listeningHost = AFFiNE.deploy ? '0.0.0.0' : 'localhost';
await app.listen(AFFiNE.server.port, listeningHost); await app.listen(AFFiNE.server.port, listeningHost);

View File

@@ -57,7 +57,7 @@ const config: PlaywrightTestConfig = {
DATABASE_URL: DATABASE_URL:
process.env.DATABASE_URL ?? process.env.DATABASE_URL ??
'postgresql://affine:affine@localhost:5432/affine', 'postgresql://affine:affine@localhost:5432/affine',
NODE_ENV: 'test', NODE_ENV: 'development',
AFFINE_ENV: process.env.AFFINE_ENV ?? 'dev', AFFINE_ENV: process.env.AFFINE_ENV ?? 'dev',
DEBUG: 'affine:*', DEBUG: 'affine:*',
FORCE_COLOR: 'true', FORCE_COLOR: 'true',

View File

@@ -44,7 +44,7 @@ const config: PlaywrightTestConfig = {
DATABASE_URL: DATABASE_URL:
process.env.DATABASE_URL ?? process.env.DATABASE_URL ??
'postgresql://affine:affine@localhost:5432/affine', 'postgresql://affine:affine@localhost:5432/affine',
NODE_ENV: 'test', NODE_ENV: 'development',
AFFINE_ENV: process.env.AFFINE_ENV ?? 'dev', AFFINE_ENV: process.env.AFFINE_ENV ?? 'dev',
DEBUG: 'affine:*', DEBUG: 'affine:*',
FORCE_COLOR: 'true', FORCE_COLOR: 'true',

View File

@@ -755,8 +755,8 @@ __metadata:
"@node-rs/jsonwebtoken": "npm:^0.5.2" "@node-rs/jsonwebtoken": "npm:^0.5.2"
"@opentelemetry/api": "npm:^1.9.0" "@opentelemetry/api": "npm:^1.9.0"
"@opentelemetry/core": "npm:^1.25.0" "@opentelemetry/core": "npm:^1.25.0"
"@opentelemetry/exporter-metrics-otlp-proto": "npm:^0.52.0" "@opentelemetry/exporter-prometheus": "npm:^0.52.0"
"@opentelemetry/exporter-trace-otlp-proto": "npm:^0.52.0" "@opentelemetry/exporter-zipkin": "npm:^1.25.0"
"@opentelemetry/host-metrics": "npm:^0.35.2" "@opentelemetry/host-metrics": "npm:^0.35.2"
"@opentelemetry/instrumentation": "npm:^0.52.0" "@opentelemetry/instrumentation": "npm:^0.52.0"
"@opentelemetry/instrumentation-graphql": "npm:^0.42.0" "@opentelemetry/instrumentation-graphql": "npm:^0.42.0"
@@ -9737,34 +9737,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@opentelemetry/exporter-metrics-otlp-http@npm:0.52.1": "@opentelemetry/exporter-prometheus@npm:^0.52.0":
version: 0.52.1 version: 0.52.1
resolution: "@opentelemetry/exporter-metrics-otlp-http@npm:0.52.1" resolution: "@opentelemetry/exporter-prometheus@npm:0.52.1"
dependencies: dependencies:
"@opentelemetry/core": "npm:1.25.1" "@opentelemetry/core": "npm:1.25.1"
"@opentelemetry/otlp-exporter-base": "npm:0.52.1"
"@opentelemetry/otlp-transformer": "npm:0.52.1"
"@opentelemetry/resources": "npm:1.25.1" "@opentelemetry/resources": "npm:1.25.1"
"@opentelemetry/sdk-metrics": "npm:1.25.1" "@opentelemetry/sdk-metrics": "npm:1.25.1"
peerDependencies: peerDependencies:
"@opentelemetry/api": ^1.3.0 "@opentelemetry/api": ^1.3.0
checksum: 10/b2836279dbeb84be8b5b97a02e658b79c3d104b663b033df0bcf9e98d9d4697649c9855ddfa1493f8b89ed83f6a43e41d6c2e71278c64944f2628394dc471c10 checksum: 10/34cb0a1e62ec5e6e53ce70fb390cc2720571c03a45942469f99bc327cdb3ac2a0602f9977917640125ac4ed8b5e6e968577441b65bd712f27e73233fd6378776
languageName: node
linkType: hard
"@opentelemetry/exporter-metrics-otlp-proto@npm:^0.52.0":
version: 0.52.1
resolution: "@opentelemetry/exporter-metrics-otlp-proto@npm:0.52.1"
dependencies:
"@opentelemetry/core": "npm:1.25.1"
"@opentelemetry/exporter-metrics-otlp-http": "npm:0.52.1"
"@opentelemetry/otlp-exporter-base": "npm:0.52.1"
"@opentelemetry/otlp-transformer": "npm:0.52.1"
"@opentelemetry/resources": "npm:1.25.1"
"@opentelemetry/sdk-metrics": "npm:1.25.1"
peerDependencies:
"@opentelemetry/api": ^1.3.0
checksum: 10/bbce23bf31a9b91ac2836b0b697dd2f853281a3e46bae58b86a0a2b747f995777a9aef77bdbb3885f06ff155d7fd6a8af3364d1348dee3427ce8f87d1ed15675
languageName: node languageName: node
linkType: hard linkType: hard
@@ -9799,7 +9781,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@opentelemetry/exporter-trace-otlp-proto@npm:0.52.1, @opentelemetry/exporter-trace-otlp-proto@npm:^0.52.0": "@opentelemetry/exporter-trace-otlp-proto@npm:0.52.1":
version: 0.52.1 version: 0.52.1
resolution: "@opentelemetry/exporter-trace-otlp-proto@npm:0.52.1" resolution: "@opentelemetry/exporter-trace-otlp-proto@npm:0.52.1"
dependencies: dependencies:
@@ -9814,7 +9796,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@opentelemetry/exporter-zipkin@npm:1.25.1": "@opentelemetry/exporter-zipkin@npm:1.25.1, @opentelemetry/exporter-zipkin@npm:^1.25.0":
version: 1.25.1 version: 1.25.1
resolution: "@opentelemetry/exporter-zipkin@npm:1.25.1" resolution: "@opentelemetry/exporter-zipkin@npm:1.25.1"
dependencies: dependencies: