@apifuse/provider-sdk 2.2.0-beta.61 → 2.2.0-beta.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,3 @@
1
- import { NativeTelemetryCollector } from "../runtime/native-telemetry.js";
2
1
  import { STATUS_CODES } from "node:http";
3
2
  import { readDiagnosticEnv, withDiagnosticEnv } from "../runtime/diagnostic-env.js";
4
3
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -77,6 +76,13 @@ import {
77
76
  import { createEnvContext } from "../runtime/env.js";
78
77
  import { executeOperation } from "../runtime/executor.js";
79
78
  import { createHttpClient } from "../runtime/http.js";
79
+ import { NativeTelemetryCollector } from "../runtime/native-telemetry.js";
80
+ import {
81
+ bindHttpTelemetry,
82
+ isSupportedHttpBinding,
83
+ warnUnsupportedHttpBinding,
84
+ } from "../runtime/http-telemetry-binding.js";
85
+ import { HttpTelemetryCollector, type HttpTelemetryLogPayload } from "../runtime/http-telemetry.js";
80
86
  import { wrapWithInstrumentation } from "../runtime/instrumentation.js";
81
87
  import type * as NativeNetworkRuntimeModule from "../runtime/native-network.js";
82
88
  import { createOcrClientFromEnv } from "../runtime/ocr.js";
@@ -153,7 +159,6 @@ import type {
153
159
  BrowserClient,
154
160
  FlowContext,
155
161
  FlowContextStore,
156
- HttpRetrySummary,
157
162
  OcrContext,
158
163
  OperationDefinition,
159
164
  OperationErrorCode,
@@ -234,29 +239,7 @@ function providerErrorCode(error: unknown): string | undefined {
234
239
  }
235
240
 
236
241
  const AUTH_FLOW_LOCALES = ["en", "ko", "ja"] as const;
237
- const retryResponseMeta = new WeakMap<ProviderContext, HttpRetrySummary>();
238
- type RetryLastErrorCode =
239
- // runtime/http.ts:178-179 preserves ambient cancellation.
240
- | "transport_cancelled"
241
- // runtime/http.ts:180-196 normalizes timeout aborts and timeout-shaped errors.
242
- | "transport_timeout"
243
- // runtime/http.ts:198-225 normalizes other native fetch failures.
244
- | "transport_network_error"
245
- // runtime/http.ts:119-126,763-771,829-837 creates upstream status errors.
246
- | "upstream_http_error"
247
- // runtime/proxy-retry-policy.ts:64-84 forwards other coded TransportErrors; the builder closes them.
248
- | "other";
249
- const RETRY_LAST_ERROR_CODES = [
250
- "transport_cancelled",
251
- "transport_timeout",
252
- "transport_network_error",
253
- "upstream_http_error",
254
- "other",
255
- ] as const satisfies readonly RetryLastErrorCode[];
256
-
257
- function tenantRetryLastErrorCode(value: string): RetryLastErrorCode {
258
- return RETRY_LAST_ERROR_CODES.find((candidate) => candidate === value) ?? "other";
259
- }
242
+ const retryResponseMeta = new WeakMap<ProviderContext, HttpTelemetryCollector>();
260
243
  const STATEFUL_INTERNAL_OPERATIONS_ROUTE = "/__apifuse/stateful/operations";
261
244
  const STATEFUL_FORWARDING_SOURCE_POD_HEADER = "x-apifuse-stateful-source-pod";
262
245
  const DEFAULT_STATEFUL_FORWARDING_MAX_SKEW_MS = 5 * 60_000;
@@ -845,6 +828,7 @@ type RequestScopeContext = {
845
828
  telemetry: RequestTelemetry;
846
829
  resolverTelemetry: ResolverTelemetryCollector;
847
830
  nativeTelemetry: NativeTelemetryCollector;
831
+ httpTelemetry: HttpTelemetryCollector;
848
832
  };
849
833
 
850
834
  function createProviderContext(
@@ -873,7 +857,6 @@ function createProviderContext(
873
857
  request.requestId,
874
858
  );
875
859
  const cache = createProviderCache({ providerId: provider.id });
876
- let wrappedContext: ProviderContext | undefined;
877
860
  const { capabilityModules } = options;
878
861
  const resolverOptions = createResolverRuntimeOptions(
879
862
  provider,
@@ -941,10 +924,7 @@ function createProviderContext(
941
924
  http: createHttpClient(baseUrl, {
942
925
  ...proxyClientOptions,
943
926
  ...(signal ? { signal } : {}),
944
- onRetrySummary: (summary) => {
945
- if (summary.attempts <= 1 || !wrappedContext) return;
946
- retryResponseMeta.set(wrappedContext, summary);
947
- },
927
+ httpTelemetry: scope.httpTelemetry,
948
928
  }),
949
929
  cache,
950
930
  state: requestState,
@@ -1015,10 +995,30 @@ function createProviderContext(
1015
995
  }),
1016
996
  }),
1017
997
  };
1018
- const context = wrapWithInstrumentation(
1019
- options.engine.attach({ provider, bindings }) as ProviderContext,
1020
- );
1021
- wrappedContext = context;
998
+ const candidateHttp = bindings.http;
999
+ const attached = options.engine.attach({ provider, bindings }) as ProviderContext;
1000
+ const hostHttp = provider.http ? attached.http : undefined;
1001
+ const supportedHostHttp = provider.http && isSupportedHttpBinding(hostHttp);
1002
+ if (provider.http && !supportedHostHttp) warnUnsupportedHttpBinding();
1003
+ const observedHttp =
1004
+ supportedHostHttp && hostHttp !== candidateHttp
1005
+ ? bindHttpTelemetry(hostHttp, scope.httpTelemetry)
1006
+ : undefined;
1007
+ const contextTarget = observedHttp
1008
+ ? new Proxy(attached, {
1009
+ get(target, property, receiver) {
1010
+ return property === "http" ? observedHttp : Reflect.get(target, property, receiver);
1011
+ },
1012
+ })
1013
+ : provider.http && !supportedHostHttp
1014
+ ? new Proxy(attached, {
1015
+ get(target, property, receiver) {
1016
+ return property === "http" ? undefined : Reflect.get(target, property, receiver);
1017
+ },
1018
+ })
1019
+ : attached;
1020
+ const context = wrapWithInstrumentation(contextTarget);
1021
+ retryResponseMeta.set(context, scope.httpTelemetry);
1022
1022
  return context;
1023
1023
  }
1024
1024
 
@@ -1199,6 +1199,7 @@ function createAuthFlowContext(
1199
1199
  http: createHttpClient(baseUrl, {
1200
1200
  ...proxyClientOptions,
1201
1201
  ...(signal ? { signal } : {}),
1202
+ httpTelemetry: scope.httpTelemetry,
1202
1203
  }),
1203
1204
  state: state.forConnection(resolveOperationConnectionId(request)),
1204
1205
  stealth: stealthBaseUrl
@@ -1288,6 +1289,7 @@ type ProviderServerLogEventBase = ProviderRequestCost & {
1288
1289
  status: number;
1289
1290
  proxy?: ProxyTelemetryLogPayload;
1290
1291
  resolver?: ResolverTelemetryLogPayload;
1292
+ http?: HttpTelemetryLogPayload;
1291
1293
  };
1292
1294
 
1293
1295
  export type ProviderServerLogEvent =
@@ -2276,10 +2278,12 @@ function createRequestScope(input: {
2276
2278
  const proxyCollector = new ProxyTelemetryCollector();
2277
2279
  const resolverCollector = new ResolverTelemetryCollector({ redact });
2278
2280
  const nativeCollector = new NativeTelemetryCollector({ redact });
2281
+ const httpCollector = new HttpTelemetryCollector({ redact });
2279
2282
  const telemetry = new RequestTelemetry(trace);
2280
2283
  telemetry.register(proxyCollector);
2281
2284
  telemetry.register(resolverCollector);
2282
2285
  telemetry.register(nativeCollector);
2286
+ telemetry.register(httpCollector);
2283
2287
  let rootRunner: <T>(fn: () => Promise<T>) => Promise<T> = (fn) => fn();
2284
2288
  let resolveRoot!: (outcome: RequestTerminalOutcome) => void;
2285
2289
  const rootTerminal = new Promise<RequestTerminalOutcome>((resolve) => {
@@ -2362,6 +2366,7 @@ function createRequestScope(input: {
2362
2366
  telemetry,
2363
2367
  resolverTelemetry: resolverCollector,
2364
2368
  nativeTelemetry: nativeCollector,
2369
+ httpTelemetry: httpCollector,
2365
2370
  seedCredentials(rawBody, kind): void {
2366
2371
  const harvested = rawRequestCredentials(rawBody, kind);
2367
2372
  sensitiveRegistry.add(harvested.values);
@@ -2581,21 +2586,13 @@ function toJsonSuccessResponse(
2581
2586
  }
2582
2587
 
2583
2588
  const cacheMeta = ctx && "cache" in ctx ? ctx.cache.responseMeta() : undefined;
2584
- const retryMeta = ctx ? retryResponseMeta.get(ctx) : undefined;
2589
+ const retry = ctx ? retryResponseMeta.get(ctx)?.toTenantRetryPayload() : undefined;
2585
2590
  type TenantCacheMeta = {
2586
2591
  hit: boolean;
2587
2592
  stale: boolean;
2588
2593
  keys: TenantOpaqueKeys;
2589
2594
  source?: ClosedEnum<NonNullable<ProviderCacheResponseMeta["source"]>>;
2590
2595
  };
2591
- type TenantRetryMeta = {
2592
- attempts: number;
2593
- retries: number;
2594
- preset?: ClosedEnum<NonNullable<HttpRetrySummary["preset"]>>;
2595
- transport: ClosedEnum<HttpRetrySummary["transport"]>;
2596
- lastErrorCode?: ClosedEnum<RetryLastErrorCode>;
2597
- lastStatus?: number;
2598
- };
2599
2596
  const cache: TenantNeutral<TenantCacheMeta> | undefined = cacheMeta
2600
2597
  ? {
2601
2598
  hit: cacheMeta.hit,
@@ -2605,22 +2602,8 @@ function toJsonSuccessResponse(
2605
2602
  ...(cacheMeta.source ? { source: closedEnum(cacheMeta.source) } : {}),
2606
2603
  }
2607
2604
  : undefined;
2608
- const retry: TenantNeutral<TenantRetryMeta> | undefined = retryMeta
2609
- ? {
2610
- attempts: retryMeta.attempts,
2611
- retries: retryMeta.retries,
2612
- ...(retryMeta.preset ? { preset: closedEnum(retryMeta.preset) } : {}),
2613
- transport: closedEnum(retryMeta.transport),
2614
- ...(retryMeta.lastErrorCode
2615
- ? {
2616
- lastErrorCode: closedEnum(tenantRetryLastErrorCode(retryMeta.lastErrorCode)),
2617
- }
2618
- : {}),
2619
- ...(retryMeta.lastStatus ? { lastStatus: retryMeta.lastStatus } : {}),
2620
- }
2621
- : undefined;
2622
2605
  const meta =
2623
- cacheMeta || retryMeta
2606
+ cacheMeta || retry
2624
2607
  ? {
2625
2608
  ...(cache
2626
2609
  ? {