@inference-net/otel-cf-workers 2.0.1 → 2.0.3

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.
package/dist/index.d.ts CHANGED
@@ -84,6 +84,7 @@ export declare interface ConsoleTransportConfig {
84
84
  pretty?: boolean;
85
85
  colors?: boolean;
86
86
  includeTimestamp?: boolean;
87
+ transformLog?: (logRecord: ReadableLogRecord) => ReadableLogRecord;
87
88
  }
88
89
 
89
90
  /**
@@ -511,7 +512,7 @@ declare class TraceState {
511
512
  private exportSpans;
512
513
  }
513
514
 
514
- export declare type Trigger = Request | MessageBatch | ScheduledController | DOConstructorTrigger | 'do-alarm' | ForwardableEmailMessage;
515
+ export declare type Trigger = Request | MessageBatch | ScheduledController | DOConstructorTrigger | 'do-alarm' | 'do-rpc' | ForwardableEmailMessage;
515
516
 
516
517
  export declare function withNextSpan(attrs: Attributes): void;
517
518
 
package/dist/index.js CHANGED
@@ -96,7 +96,7 @@ function passthroughGet(target, prop, thisArg) {
96
96
  }
97
97
  }
98
98
 
99
- const PACKAGE_VERSION = "2.0.1";
99
+ const PACKAGE_VERSION = "2.0.3";
100
100
  const PACKAGE_NAME = "@inference-net/otel-cf-workers";
101
101
  const ATTR_CLOUDFLARE_COLO = "cloudflare.colo";
102
102
  const ATTR_CLOUDFLARE_RAY_ID = "cloudflare.ray_id";
@@ -224,6 +224,10 @@ const ATTR_CLOUDFLARE_IMAGES_REQUIRE_SIGNED_URLS = "cloudflare.images.require_si
224
224
  const ATTR_CLOUDFLARE_RATE_LIMIT_KEY = "cloudflare.rate_limit.key";
225
225
  const ATTR_CLOUDFLARE_RATE_LIMIT_ALLOWED = "cloudflare.rate_limit.allowed";
226
226
  const ATTR_CLOUDFLARE_RATE_LIMIT_SUCCESS = "cloudflare.rate_limit.success";
227
+ const ATTR_CLOUDFLARE_JSRPC_METHOD = "cloudflare.jsrpc.method";
228
+ const ATTR_RPC_SYSTEM = "rpc.system";
229
+ const ATTR_RPC_SERVICE = "rpc.service";
230
+ const ATTR_RPC_METHOD = "rpc.method";
227
231
  const DEFAULT_OTLP_HEADERS = {
228
232
  accept: "application/json",
229
233
  "content-type": "application/json",
@@ -2920,6 +2924,79 @@ function instrumentSQLStorage(sql) {
2920
2924
  return wrap(sql, sqlHandler);
2921
2925
  }
2922
2926
 
2927
+ const RPC_CONTEXT_MARKER = "__otel_rpc_ctx__";
2928
+ function isRpcContextCarrier(obj) {
2929
+ return typeof obj === "object" && obj !== null && RPC_CONTEXT_MARKER in obj && obj[RPC_CONTEXT_MARKER] === true;
2930
+ }
2931
+ function injectRpcContext(ctx = context.active()) {
2932
+ const carrier = {
2933
+ [RPC_CONTEXT_MARKER]: true,
2934
+ headers: {}
2935
+ };
2936
+ propagation.inject(ctx, carrier.headers, {
2937
+ set: (headers, key, value) => {
2938
+ headers[key] = typeof value === "string" ? value : String(value);
2939
+ }
2940
+ });
2941
+ return carrier;
2942
+ }
2943
+ function extractRpcContext(carrier) {
2944
+ return propagation.extract(context.active(), carrier.headers, {
2945
+ get(headers, key) {
2946
+ return headers[key] || void 0;
2947
+ },
2948
+ keys(headers) {
2949
+ return Object.keys(headers);
2950
+ }
2951
+ });
2952
+ }
2953
+ function extractAndRemoveRpcContext(args) {
2954
+ if (args.length > 0 && isRpcContextCarrier(args[0])) {
2955
+ const carrier = args[0];
2956
+ const extractedContext = extractRpcContext(carrier);
2957
+ const cleanedArgs = args.slice(1);
2958
+ return [extractedContext, cleanedArgs];
2959
+ }
2960
+ return [void 0, args];
2961
+ }
2962
+
2963
+ function instrumentRpcMethod(method, methodName, nsName, stubId) {
2964
+ const tracer = trace.getTracer("do_rpc_client");
2965
+ const rpcHandler = {
2966
+ apply: async (target, thisArg, argArray) => {
2967
+ const attributes = {
2968
+ [ATTR_RPC_SYSTEM]: "cloudflare_rpc",
2969
+ [ATTR_RPC_SERVICE]: nsName,
2970
+ [ATTR_RPC_METHOD]: methodName,
2971
+ [ATTR_CLOUDFLARE_JSRPC_METHOD]: methodName,
2972
+ "do.namespace": nsName,
2973
+ "do.id": stubId.toString(),
2974
+ "do.id.name": stubId.name
2975
+ };
2976
+ const options = {
2977
+ kind: SpanKind.CLIENT,
2978
+ attributes
2979
+ };
2980
+ const spanName = `RPC ${nsName}.${methodName}`;
2981
+ return tracer.startActiveSpan(spanName, options, async (span) => {
2982
+ try {
2983
+ const contextCarrier = injectRpcContext(context.active());
2984
+ const argsWithContext = [contextCarrier, ...argArray];
2985
+ const result = await Reflect.apply(target, thisArg, argsWithContext);
2986
+ span.setStatus({ code: SpanStatusCode.OK });
2987
+ return result;
2988
+ } catch (error) {
2989
+ span.recordException(error);
2990
+ span.setStatus({ code: SpanStatusCode.ERROR });
2991
+ throw error;
2992
+ } finally {
2993
+ span.end();
2994
+ }
2995
+ });
2996
+ }
2997
+ };
2998
+ return wrap(method, rpcHandler);
2999
+ }
2923
3000
  function instrumentBindingStub(stub, nsName) {
2924
3001
  const stubHandler = {
2925
3002
  get(target, prop, receiver) {
@@ -2933,7 +3010,11 @@ function instrumentBindingStub(stub, nsName) {
2933
3010
  };
2934
3011
  return instrumentClientFetch(fetcher, () => ({ includeTraceContext: true }), attrs);
2935
3012
  } else {
2936
- return passthroughGet(target, prop, receiver);
3013
+ const value = passthroughGet(target, prop, receiver);
3014
+ if (typeof value === "function" && typeof prop === "string") {
3015
+ return instrumentRpcMethod(value, prop, nsName, target.id);
3016
+ }
3017
+ return value;
2937
3018
  }
2938
3019
  }
2939
3020
  };
@@ -3062,19 +3143,47 @@ function instrumentAlarmFn(alarmFn, initialiser, env, id) {
3062
3143
  };
3063
3144
  return wrap(alarmFn, alarmHandler);
3064
3145
  }
3065
- function instrumentAnyFn(fn, initialiser, env, _id) {
3066
- if (!fn) return void 0;
3146
+ function instrumentRpcHandlerMethod(fn, methodName, initialiser, env, id) {
3147
+ if (!fn) return fn;
3067
3148
  const fnHandler = {
3068
3149
  async apply(target, thisArg, argArray) {
3069
3150
  thisArg = unwrap(thisArg);
3070
- const config = initialiser(env, "do-alarm");
3071
- const context$1 = setConfig(config);
3072
- try {
3073
- const bound = target.bind(unwrap(thisArg));
3074
- return await context.with(context$1, () => bound.apply(thisArg, argArray), void 0);
3075
- } catch (error) {
3076
- throw error;
3077
- }
3151
+ const config = initialiser(env, "do-rpc");
3152
+ const [extractedContext, cleanedArgs] = extractAndRemoveRpcContext(argArray);
3153
+ let context$1 = extractedContext || context.active();
3154
+ context$1 = setConfig(config, context$1);
3155
+ const tracer = trace.getTracer("do_rpc_handler");
3156
+ const doName = id.name || id.toString();
3157
+ const executeRpc = async () => {
3158
+ const attributes = {
3159
+ [ATTR_RPC_SYSTEM]: "cloudflare_rpc",
3160
+ [ATTR_RPC_METHOD]: methodName,
3161
+ [ATTR_CLOUDFLARE_JSRPC_METHOD]: methodName,
3162
+ [SemanticAttributes.FAAS_TRIGGER]: "rpc",
3163
+ "do.id": id.toString(),
3164
+ "do.name": id.name
3165
+ };
3166
+ const options = {
3167
+ kind: SpanKind.SERVER,
3168
+ attributes
3169
+ };
3170
+ const spanName = `Durable Object RPC ${doName}.${methodName}`;
3171
+ return tracer.startActiveSpan(spanName, options, async (span) => {
3172
+ try {
3173
+ const bound = target.bind(thisArg);
3174
+ const result = await bound.apply(thisArg, cleanedArgs);
3175
+ span.setStatus({ code: SpanStatusCode.OK });
3176
+ return result;
3177
+ } catch (error) {
3178
+ span.recordException(error);
3179
+ span.setStatus({ code: SpanStatusCode.ERROR });
3180
+ throw error;
3181
+ } finally {
3182
+ span.end();
3183
+ }
3184
+ });
3185
+ };
3186
+ return await context.with(context$1, executeRpc);
3078
3187
  }
3079
3188
  };
3080
3189
  return wrap(fn, fnHandler);
@@ -3094,9 +3203,9 @@ function instrumentDurableObject(doObj, initialiser, env, state, classStyle) {
3094
3203
  return instrumentAlarmFn(alarmFn, initialiser, env, state.id);
3095
3204
  } else {
3096
3205
  const result = Reflect.get(target, prop);
3097
- if (typeof result === "function") {
3206
+ if (typeof result === "function" && typeof prop === "string") {
3098
3207
  result.bind(doObj);
3099
- return instrumentAnyFn(result, initialiser, env, state.id);
3208
+ return instrumentRpcHandlerMethod(result, prop, initialiser, env, state.id);
3100
3209
  }
3101
3210
  return result;
3102
3211
  }
@@ -3583,7 +3692,8 @@ class ConsoleTransport {
3583
3692
  this.options = {
3584
3693
  pretty: options.pretty ?? true,
3585
3694
  colors: options.colors ?? false,
3586
- includeTimestamp: options.includeTimestamp ?? true
3695
+ includeTimestamp: options.includeTimestamp ?? true,
3696
+ transformLog: options.transformLog ?? ((l) => l)
3587
3697
  };
3588
3698
  }
3589
3699
  export(logs, callback) {