UNPKG

@microsoft/teams.api

Version:

<p> <a href="https://www.npmjs.com/package/@microsoft/teams.api" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.api/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.api?activeTab=code" t

1 lines • 5.96 kB
{"version":3,"sources":["../../src/clients/api-outbound-middleware.ts"],"names":[],"mappings":";;;;AAoBA,MAAM,+BAAA,0BAAyC,+CAA+C,CAAA;AAoBvF,SAAS,wBAAA,CACd,UACA,UAAA,EACyB;AACzB,EAAA,MAAM,IAAA,GAAO,EAAE,GAAI,UAAA,IAAc,EAAC,EAAG;AACrC,EAAA,IAAA,CAAK,+BAA+B,CAAA,GAAI,QAAA;AACxC,EAAA,OAAO,IAAA;AACT;AASO,SAAS,qCAAqC,MAAA,EAAoG;AACvJ,EAAA,IAAI,CAAC,OAAO,WAAA,CAAY,IAAA,CAAK,CAAC,UAAA,KAAe,UAAA,YAAsB,8BAA8B,CAAA,EAAG;AAClG,IAAA,MAAA,CAAO,GAAA,CAAI,IAAI,8BAAA,EAAgC,CAAA;AAAA,EACjD;AACF;AAOO,MAAM,8BAAA,CAAqD;AAAA,EAChE,MAAM,MAAA,CACJ,OAAA,EACA,IAAA,EACY;AACZ,IAAA,MAAM,QAAA,GAAW,+BAAA,CAAgC,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA;AAC1E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,IAAA,EAAK;AAAA,IACd;AAEA,IAAA,OAAO,mBAAkB,CAAE,eAAA;AAAA,MACzB,cAAA,CAAe,SAAA;AAAA,MACf;AAAA,QACE,MAAM,QAAA,CAAS,MAAA;AAAA,QACf,YAAY,QAAA,CAAS;AAAA,OACvB;AAAA,MACA,OAAO,IAAA,KAAS;AACd,QAAA,0BAAA,CAA2B,SAAS,SAAS,CAAA;AAE7C,QAAA,IAAI;AACF,UAAA,IAAI,GAAA;AAIJ,UAAA,IAAI;AACF,YAAA,GAAA,GAAM,MAAM,IAAA,EAAK;AAAA,UACnB,SAAS,KAAA,EAAO;AACd,YAAA,2BAAA,CAA4B,SAAS,SAAS,CAAA;AAC9C,YAAA,uBAAA,CAAwB,MAAM,KAAK,CAAA;AACnC,YAAA,MAAM,KAAA;AAAA,UACR;AAOA,UAAA,IAAI,SAAS,UAAA,EAAY;AACvB,YAAA,IAAI;AACF,cAAA,MAAM,QAAA,CAAS,UAAA,CAAW,IAAA,EAAM,GAAoB,CAAA;AAAA,YACtD,SAAS,SAAA,EAAW;AAClB,cAAA,OAAA,CAAQ,GAAA,CAAI,IAAA;AAAA,gBACV,6DAAA;AAAA,gBACA;AAAA,eACF;AAAA,YACF;AAAA,UACF;AAEA,UAAA,OAAO,GAAA;AAAA,QACT,CAAA,SAAE;AACA,UAAA,IAAA,CAAK,GAAA,EAAI;AAAA,QACX;AAAA,MACF;AAAA,KACF;AAAA,EACF;AACF;AAEA,SAAS,gCACP,UAAA,EAC0C;AAC1C,EAAA,OAAQ,aAA4D,+BAA+B,CAAA;AACrG","file":"api-outbound-middleware.mjs","sourcesContent":["import { SpanKind, type Span } from '@opentelemetry/api';\nimport type { AxiosResponse } from 'axios';\n\nimport type {\n Middleware,\n MiddlewareContext,\n MiddlewareNext\n} from '@microsoft/teams.common';\n\nimport {\n API_SPAN_NAMES,\n type ConversationActivityOperation\n} from '../diagnostics/constants';\nimport {\n getTeamsApiTracer,\n recordTeamsApiException,\n recordTeamsApiOutboundCall,\n recordTeamsApiOutboundError\n} from '../diagnostics/helpers';\n\nconst apiOutboundTelemetryMetadataKey = Symbol('Microsoft.Teams.Api.outboundTelemetryMetadata');\n\ntype ApiOutboundTelemetryMetadata = {\n readonly operation: ConversationActivityOperation;\n readonly attributes: Record<string, string>;\n readonly onResponse?: (span: Span, res: AxiosResponse) => void | Promise<void>;\n};\n\ntype ApiOutboundTelemetryExtensions = Record<string, unknown> & {\n [apiOutboundTelemetryMetadataKey]?: ApiOutboundTelemetryMetadata;\n};\n\n/**\n * @internal\n * Creates SDK-private request metadata for API outbound telemetry.\n *\n * API client methods use this immediately before calling the shared\n * `HttpClient` so outbound telemetry middleware can create the span and\n * metrics without each method managing telemetry mechanics directly.\n */\nexport function withApiOutboundTelemetry(\n metadata: ApiOutboundTelemetryMetadata,\n extensions?: Record<string, unknown>\n): Record<string, unknown> {\n const next = { ...(extensions ?? {}) } as ApiOutboundTelemetryExtensions;\n next[apiOutboundTelemetryMetadataKey] = metadata;\n return next;\n}\n\n/**\n * @internal\n * Ensures Teams API outbound telemetry middleware is registered once.\n *\n * API client construction calls this after creating or receiving the common\n * `HttpClient`; callers can inspect `client.middlewares` for dedupe.\n */\nexport function ensureApiOutboundTelemetryMiddleware(client: { readonly middlewares: readonly Middleware[]; use(middleware: Middleware): number }): void {\n if (!client.middlewares.some((middleware) => middleware instanceof ApiOutboundTelemetryMiddleware)) {\n client.use(new ApiOutboundTelemetryMiddleware());\n }\n}\n\n/**\n * @internal\n * Common HTTP middleware that owns Teams API outbound span lifecycle, metrics,\n * exception recording, and optional response hooks.\n */\nexport class ApiOutboundTelemetryMiddleware implements Middleware {\n async invoke<R = AxiosResponse, D = any>(\n context: MiddlewareContext<D>,\n next: MiddlewareNext<R>\n ): Promise<R> {\n const metadata = getApiOutboundTelemetryMetadata(context.config.extensions);\n if (!metadata) {\n return next();\n }\n\n return getTeamsApiTracer().startActiveSpan(\n API_SPAN_NAMES.apiClient,\n {\n kind: SpanKind.CLIENT,\n attributes: metadata.attributes,\n },\n async (span) => {\n recordTeamsApiOutboundCall(metadata.operation);\n\n try {\n let res: R;\n\n // next() owns the error path: only genuine call failures are counted\n // as outbound errors and recorded as exceptions on the span.\n try {\n res = await next();\n } catch (error) {\n recordTeamsApiOutboundError(metadata.operation);\n recordTeamsApiException(span, error);\n throw error;\n }\n\n // Telemetry response hooks run in their own try, separate from\n // next(), so they can never fail the underlying API call: a throwing\n // or rejecting hook would otherwise discard a successful response, be\n // counted as an outbound error, and propagate to the caller. Isolate\n // the hook and swallow (logging) any failure.\n if (metadata.onResponse) {\n try {\n await metadata.onResponse(span, res as AxiosResponse);\n } catch (hookError) {\n context.log.warn(\n 'Microsoft.Teams.Api outbound telemetry response hook failed',\n hookError\n );\n }\n }\n\n return res;\n } finally {\n span.end();\n }\n }\n );\n }\n}\n\nfunction getApiOutboundTelemetryMetadata(\n extensions: Record<string, unknown> | undefined\n): ApiOutboundTelemetryMetadata | undefined {\n return (extensions as ApiOutboundTelemetryExtensions | undefined)?.[apiOutboundTelemetryMetadataKey];\n}\n"]}