Yuki Takei 1 год назад
Родитель
Сommit
648013f8a7
2 измененных файлов с 63 добавлено и 69 удалено
  1. 59 64
      apps/app/src/features/opentelemetry/server/start.ts
  2. 4 5
      apps/app/src/server/crowi/index.js

+ 59 - 64
apps/app/src/features/opentelemetry/server/start.ts

@@ -8,9 +8,9 @@ import type { NodeSDKConfiguration } from '@opentelemetry/sdk-node';
 import { NodeSDK } from '@opentelemetry/sdk-node';
 import { NodeSDK } from '@opentelemetry/sdk-node';
 import { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_INSTANCE_ID, SEMRESATTRS_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
 import { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_INSTANCE_ID, SEMRESATTRS_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
 
 
+import { configManager } from '~/server/service/config-manager';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
-import { configManager } from '../service/config-manager';
 
 
 const logger = loggerFactory('growi:opentelemetry');
 const logger = loggerFactory('growi:opentelemetry');
 
 
@@ -90,72 +90,67 @@ class BunyanOTelLogger implements DiagLogger {
 diag.setLogger(new BunyanOTelLogger());
 diag.setLogger(new BunyanOTelLogger());
 
 
 
 
-export class OpenTelemetry {
-
-  name: string;
-
-  version: string;
-
-  sdkInstance: NodeSDK;
-
-  constructor(name: string, version: string) {
-    this.name = name;
-    this.version = version;
-  }
-
-  private generateNodeSDKConfiguration(): Partial<NodeSDKConfiguration> {
-    return {
-      resource: new Resource({
-        [SEMRESATTRS_SERVICE_NAME]: this.name,
-        [SEMRESATTRS_SERVICE_INSTANCE_ID]: configManager.getConfig('crowi', 'otel:serviceInstanceId'),
-        [SEMRESATTRS_SERVICE_VERSION]: this.version,
-      }),
-      traceExporter: new OTLPTraceExporter(),
-      metricReader: new PeriodicExportingMetricReader({
-        exporter: new OTLPMetricExporter(),
-        exportIntervalMillis: 10000,
-      }),
-      instrumentations: [getNodeAutoInstrumentations({
-        // disable fs instrumentation since this generates very large amount of traces
-        // see: https://opentelemetry.io/docs/languages/js/libraries/#registration
-        '@opentelemetry/instrumentation-fs': {
-          enabled: false,
-        },
-      })],
-    };
-  }
+let sdkInstance: NodeSDK;
+
+function generateNodeSDKConfiguration(name: string, version: string): Partial<NodeSDKConfiguration> {
+  return {
+    resource: new Resource({
+      [SEMRESATTRS_SERVICE_NAME]: name,
+      [SEMRESATTRS_SERVICE_INSTANCE_ID]: configManager.getConfig('crowi', 'otel:serviceInstanceId'),
+      [SEMRESATTRS_SERVICE_VERSION]: version,
+    }),
+    traceExporter: new OTLPTraceExporter(),
+    metricReader: new PeriodicExportingMetricReader({
+      exporter: new OTLPMetricExporter(),
+      exportIntervalMillis: 10000,
+    }),
+    instrumentations: [getNodeAutoInstrumentations({
+      '@opentelemetry/instrumentation-bunyan': {
+        enabled: false,
+      },
+      // disable fs instrumentation since this generates very large amount of traces
+      // see: https://opentelemetry.io/docs/languages/js/libraries/#registration
+      '@opentelemetry/instrumentation-fs': {
+        enabled: false,
+      },
+    })],
+  };
+}
 
 
-  /**
-   * Overwrite "OTEL_SDK_DISABLED" env var before sdk.start() is invoked if needed.
-   * Since otel library sees it.
-   */
-  private overwriteSdkDisabled(): void {
-    const instrumentationEnabled = configManager.getConfig('crowi', 'otel:enabled');
-    if (instrumentationEnabled === false) {
-      logger.warn("OTEL_SDK_DISABLED will be set 'true' since GROWI's 'otel:enabled' config is false.");
-      process.env.OTEL_SDK_DISABLED = 'true';
-    }
+/**
+ * Overwrite "OTEL_SDK_DISABLED" env var before sdk.start() is invoked if needed.
+ * Since otel library sees it.
+ */
+function overwriteSdkDisabled(): void {
+  const instrumentationEnabled = configManager.getConfig('crowi', 'otel:enabled');
+  if (instrumentationEnabled === false) {
+    logger.warn("OTEL_SDK_DISABLED will be set 'true' since GROWI's 'otel:enabled' config is false.");
+    process.env.OTEL_SDK_DISABLED = 'true';
   }
   }
+}
 
 
-  public startInstrumentation(): void {
-    this.overwriteSdkDisabled();
-
-    this.sdkInstance = new NodeSDK(this.generateNodeSDKConfiguration());
-    this.sdkInstance.start();
-  }
+export const startInstrumentation = (version: string): void => {
+  overwriteSdkDisabled();
 
 
-  public async shutdownInstrumentation(): Promise<void> {
-    await this.sdkInstance.shutdown();
-
-    // メモ: 以下の restart コードは動かない
-    // span/metrics ともに何も出なくなる
-    // そもそも、restart するような使い方が出来なさそう?
-    // see: https://github.com/open-telemetry/opentelemetry-specification/issues/27/
-    // const sdk = new NodeSDK({...});
-    // sdk.start();
-    // await sdk.shutdown().catch(console.error);
-    // const newSdk = new NodeSDK({...});
-    // newSdk.start();
+  if (sdkInstance != null) {
+    logger.warn('OpenTelemetry instrumentation already started');
+    return;
   }
   }
 
 
-}
+  sdkInstance = new NodeSDK(generateNodeSDKConfiguration('next-app', version));
+  sdkInstance.start();
+};
+
+// public async shutdownInstrumentation(): Promise<void> {
+//   await this.sdkInstance.shutdown();
+
+//   // メモ: 以下の restart コードは動かない
+//   // span/metrics ともに何も出なくなる
+//   // そもそも、restart するような使い方が出来なさそう?
+//   // see: https://github.com/open-telemetry/opentelemetry-specification/issues/27/
+//   // const sdk = new NodeSDK({...});
+//   // sdk.start();
+//   // await sdk.shutdown().catch(console.error);
+//   // const newSdk = new NodeSDK({...});
+//   // newSdk.start();
+// }

+ 4 - 5
apps/app/src/server/crowi/index.js

@@ -14,6 +14,7 @@ import { KeycloakUserGroupSyncService } from '~/features/external-user-group/ser
 import { LdapUserGroupSyncService } from '~/features/external-user-group/server/service/ldap-user-group-sync';
 import { LdapUserGroupSyncService } from '~/features/external-user-group/server/service/ldap-user-group-sync';
 import OpenaiThreadDeletionCronService from '~/features/openai/server/services/thread-deletion-cron';
 import OpenaiThreadDeletionCronService from '~/features/openai/server/services/thread-deletion-cron';
 import OpenaiVectorStoreFileDeletionCronService from '~/features/openai/server/services/vector-store-file-deletion-cron';
 import OpenaiVectorStoreFileDeletionCronService from '~/features/openai/server/services/vector-store-file-deletion-cron';
+import { startInstrumentation } from '~/features/opentelemetry/server';
 import QuestionnaireService from '~/features/questionnaire/server/service/questionnaire';
 import QuestionnaireService from '~/features/questionnaire/server/service/questionnaire';
 import QuestionnaireCronService from '~/features/questionnaire/server/service/questionnaire-cron';
 import QuestionnaireCronService from '~/features/questionnaire/server/service/questionnaire-cron';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
@@ -43,7 +44,6 @@ import { UserNotificationService } from '../service/user-notification';
 import { initializeYjsService } from '../service/yjs';
 import { initializeYjsService } from '../service/yjs';
 import { getModelSafely, getMongoUri, mongoOptions } from '../util/mongoose-utils';
 import { getModelSafely, getMongoUri, mongoOptions } from '../util/mongoose-utils';
 
 
-import { OpenTelemetry } from './opentelemetry';
 import { setupModelsDependentOnCrowi } from './setup-models';
 import { setupModelsDependentOnCrowi } from './setup-models';
 
 
 
 
@@ -146,6 +146,9 @@ Crowi.prototype.init = async function() {
   await this.setupSessionConfig();
   await this.setupSessionConfig();
   this.setupCron();
   this.setupCron();
 
 
+  // start OpenTelemetry
+  startInstrumentation();
+
   // setup messaging services
   // setup messaging services
   await this.setupS2sMessagingService();
   await this.setupS2sMessagingService();
   await this.setupSocketIoService();
   await this.setupSocketIoService();
@@ -460,10 +463,6 @@ Crowi.prototype.start = async function() {
   await this.init();
   await this.init();
   await this.buildServer();
   await this.buildServer();
 
 
-  // 具体的な設定値については、https://redmine.weseek.co.jp/issues/144351 で決定予定
-  const otel = new OpenTelemetry('next-app', this.version);
-  otel.startInstrumentation();
-
   // setup Next.js
   // setup Next.js
   this.nextApp = next({ dev });
   this.nextApp = next({ dev });
   await this.nextApp.prepare();
   await this.nextApp.prepare();