{"version":3,"file":"serverUtils.js","sourceRoot":"","sources":["../../src/serverUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Symbol to include on grpc call if it has already emitted an error event.\n * grpc events that emit 'error' will also emit 'finish' and so only the\n * error event should be processed.\n */\n\nimport { errorMonitor } from 'node:events';\n\nimport type {\n  ClientReadableStream,\n  handleBidiStreamingCall,\n  handleServerStreamingCall,\n  handleUnaryCall,\n  ServiceError,\n} from '@grpc/grpc-js';\nimport type { Span } from '@opentelemetry/api';\n\nimport type {\n  ServerCallWithMeta,\n  SendUnaryDataCallback,\n  GrpcEmitter,\n  HandleCall,\n} from './internal-types';\nimport type { IgnoreMatcher } from './types';\n\nimport { context, SpanStatusCode } from '@opentelemetry/api';\n\nimport {\n  _grpcStatusCodeToOpenTelemetryStatusCode,\n  _methodIsIgnored,\n} from './utils';\nimport { AttributeNames } from './enums/AttributeNames';\nimport {\n  ATTR_RPC_GRPC_STATUS_CODE,\n  RPC_GRPC_STATUS_CODE_VALUE_OK,\n} from './semconv';\n\nexport const CALL_SPAN_ENDED = Symbol('opentelemetry call span ended');\n\n/**\n * Handle patching for serverStream and Bidi type server handlers\n */\nfunction serverStreamAndBidiHandler<RequestType, ResponseType>(\n  span: Span,\n  call: GrpcEmitter,\n  original:\n    | handleBidiStreamingCall<RequestType, ResponseType>\n    | handleServerStreamingCall<RequestType, ResponseType>\n): void {\n  let spanEnded = false;\n  const endSpan = () => {\n    if (!spanEnded) {\n      spanEnded = true;\n      span.end();\n    }\n  };\n\n  context.bind(context.active(), call);\n  call.on('finish', () => {\n    // @grpc/js does not expose a way to check if this call also emitted an error,\n    // e.g. call.status.code !== 0\n    if (call[CALL_SPAN_ENDED]) {\n      return;\n    }\n\n    // Set the \"grpc call had an error\" flag\n    call[CALL_SPAN_ENDED] = true;\n\n    span.setStatus({\n      code: SpanStatusCode.UNSET,\n    });\n    span.setAttribute(ATTR_RPC_GRPC_STATUS_CODE, RPC_GRPC_STATUS_CODE_VALUE_OK);\n\n    endSpan();\n  });\n\n  call.on(errorMonitor, (err: ServiceError) => {\n    if (call[CALL_SPAN_ENDED]) {\n      return;\n    }\n\n    // Set the \"grpc call had an error\" flag\n    call[CALL_SPAN_ENDED] = true;\n\n    span.setStatus({\n      code: _grpcStatusCodeToOpenTelemetryStatusCode(err.code),\n      message: err.message,\n    });\n    span.setAttributes({\n      [AttributeNames.GRPC_ERROR_NAME]: err.name,\n      [AttributeNames.GRPC_ERROR_MESSAGE]: err.message,\n      [ATTR_RPC_GRPC_STATUS_CODE]: err.code,\n    });\n    endSpan();\n  });\n\n  // TODO: Investigate this call/signature – it was inherited from very old\n  // code and the `this: {}` is highly suspicious, and likely isn't doing\n  // anything useful. There is probably a more precise cast we can do here.\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n  return (original as Function).call({}, call);\n}\n\n/**\n * Handle patching for clientStream and unary type server handlers\n */\nfunction clientStreamAndUnaryHandler<RequestType, ResponseType>(\n  span: Span,\n  call: ServerCallWithMeta<RequestType, ResponseType>,\n  callback: SendUnaryDataCallback<ResponseType>,\n  original:\n    | handleUnaryCall<RequestType, ResponseType>\n    | ClientReadableStream<RequestType>\n): void {\n  const patchedCallback: SendUnaryDataCallback<ResponseType> = (\n    err: ServiceError | null,\n    value?: ResponseType\n  ) => {\n    if (err) {\n      if (err.code) {\n        span.setStatus({\n          code: _grpcStatusCodeToOpenTelemetryStatusCode(err.code),\n          message: err.message,\n        });\n        span.setAttribute(ATTR_RPC_GRPC_STATUS_CODE, err.code);\n      }\n      span.setAttributes({\n        [AttributeNames.GRPC_ERROR_NAME]: err.name,\n        [AttributeNames.GRPC_ERROR_MESSAGE]: err.message,\n      });\n    } else {\n      span.setStatus({ code: SpanStatusCode.UNSET });\n      span.setAttribute(\n        ATTR_RPC_GRPC_STATUS_CODE,\n        RPC_GRPC_STATUS_CODE_VALUE_OK\n      );\n    }\n\n    span.end();\n    return callback(err, value);\n  };\n\n  context.bind(context.active(), call);\n\n  // TODO: Investigate this call/signature – it was inherited from very old\n  // code and the `this: {}` is highly suspicious, and likely isn't doing\n  // anything useful. There is probably a more precise cast we can do here.\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n  return (original as Function).call({}, call, patchedCallback);\n}\n\n/**\n * Patch callback or EventEmitter provided by `originalFunc` and set appropriate `span`\n * properties based on its result.\n */\nexport function handleServerFunction<RequestType, ResponseType>(\n  span: Span,\n  type: string,\n  originalFunc: HandleCall<RequestType, ResponseType>,\n  call: ServerCallWithMeta<RequestType, ResponseType>,\n  callback: SendUnaryDataCallback<unknown>\n): void {\n  switch (type) {\n    case 'unary':\n    case 'clientStream':\n    case 'client_stream':\n      return clientStreamAndUnaryHandler(\n        span,\n        call,\n        callback,\n        originalFunc as\n          | handleUnaryCall<RequestType, ResponseType>\n          | ClientReadableStream<RequestType>\n      );\n    case 'serverStream':\n    case 'server_stream':\n    case 'bidi':\n      return serverStreamAndBidiHandler(\n        span,\n        call,\n        originalFunc as\n          | handleBidiStreamingCall<RequestType, ResponseType>\n          | handleServerStreamingCall<RequestType, ResponseType>\n      );\n    default:\n      break;\n  }\n}\n\n/**\n * Does not patch any callbacks or EventEmitters to omit tracing on requests\n * that should not be traced.\n */\nexport function handleUntracedServerFunction<RequestType, ResponseType>(\n  type: string,\n  originalFunc: HandleCall<RequestType, ResponseType>,\n  call: ServerCallWithMeta<RequestType, ResponseType>,\n  callback: SendUnaryDataCallback<unknown>\n): void {\n  switch (type) {\n    case 'unary':\n    case 'clientStream':\n    case 'client_stream':\n      // TODO: Investigate this call/signature – it was inherited from very old\n      // code and the `this: {}` is highly suspicious, and likely isn't doing\n      // anything useful. There is probably a more precise cast we can do here.\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n      return (originalFunc as Function).call({}, call, callback);\n    case 'serverStream':\n    case 'server_stream':\n    case 'bidi':\n      // TODO: Investigate this call/signature – it was inherited from very old\n      // code and the `this: {}` is highly suspicious, and likely isn't doing\n      // anything useful. There is probably a more precise cast we can do here.\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n      return (originalFunc as Function).call({}, call);\n    default:\n      break;\n  }\n}\n\n/**\n * Returns true if the server call should not be traced.\n */\nexport function shouldNotTraceServerCall(\n  methodName: string,\n  ignoreGrpcMethods?: IgnoreMatcher[]\n): boolean {\n  const parsedName = methodName.split('/');\n  return _methodIsIgnored(\n    parsedName[parsedName.length - 1] || methodName,\n    ignoreGrpcMethods\n  );\n}\n"]}