node-sdk-configuration.ts 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
  2. import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
  3. import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
  4. import type { Resource } from '@opentelemetry/resources';
  5. import { resourceFromAttributes } from '@opentelemetry/resources';
  6. import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
  7. import type { NodeSDKConfiguration } from '@opentelemetry/sdk-node';
  8. import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
  9. import { configManager } from '~/server/service/config-manager';
  10. import { getGrowiVersion } from '~/utils/growi-version';
  11. import { httpInstrumentationConfig as httpInstrumentationConfigForAnonymize } from './anonymization';
  12. import { ATTR_SERVICE_INSTANCE_ID } from './semconv';
  13. type Option = {
  14. enableAnonymization?: boolean,
  15. }
  16. type Configuration = Partial<NodeSDKConfiguration> & {
  17. resource: Resource;
  18. };
  19. let resource: Resource;
  20. let configuration: Configuration;
  21. export const generateNodeSDKConfiguration = (opts?: Option): Configuration => {
  22. if (configuration == null) {
  23. const version = getGrowiVersion();
  24. resource = resourceFromAttributes({
  25. [ATTR_SERVICE_NAME]: 'growi',
  26. [ATTR_SERVICE_VERSION]: version,
  27. });
  28. // Data anonymization configuration
  29. const httpInstrumentationConfig = opts?.enableAnonymization ? httpInstrumentationConfigForAnonymize : {};
  30. configuration = {
  31. resource,
  32. traceExporter: new OTLPTraceExporter(),
  33. metricReader: new PeriodicExportingMetricReader({
  34. exporter: new OTLPMetricExporter(),
  35. }),
  36. instrumentations: [getNodeAutoInstrumentations({
  37. '@opentelemetry/instrumentation-bunyan': {
  38. enabled: false,
  39. },
  40. // disable fs instrumentation since this generates very large amount of traces
  41. // see: https://opentelemetry.io/docs/languages/js/libraries/#registration
  42. '@opentelemetry/instrumentation-fs': {
  43. enabled: false,
  44. },
  45. // HTTP instrumentation with anonymization
  46. '@opentelemetry/instrumentation-http': {
  47. enabled: true,
  48. ...httpInstrumentationConfig,
  49. },
  50. })],
  51. };
  52. }
  53. return configuration;
  54. };
  55. /**
  56. * Generate additional attributes after database initialization
  57. * This function should be called after database is available
  58. */
  59. export const generateAdditionalResourceAttributes = async(opts?: Option): Promise<Resource> => {
  60. if (resource == null) {
  61. throw new Error('Resource is not initialized. Call generateNodeSDKConfiguration first.');
  62. }
  63. const serviceInstanceId = configManager.getConfig('otel:serviceInstanceId')
  64. ?? configManager.getConfig('app:serviceInstanceId');
  65. const { getApplicationResourceAttributes, getOsResourceAttributes } = await import('./custom-resource-attributes');
  66. return resource.merge(resourceFromAttributes({
  67. [ATTR_SERVICE_INSTANCE_ID]: serviceInstanceId,
  68. ...await getApplicationResourceAttributes(),
  69. ...await getOsResourceAttributes(),
  70. }));
  71. };