From 83eb364a0c6b911f4e3759f1ca2cf5d31f65aac5 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 13 Dec 2024 07:34:24 -0800 Subject: [PATCH] Implement the tail stream RPC interface (#3228) * Implement tracing::TailStreamWriter * Add the streaming-tail-workers autogate * Implement the tail stream rpc interface * Update type snapshot --- samples/tail-workers/config.capnp | 5 +- samples/tail-workers/tail.js | 5 +- src/workerd/api/global-scope.h | 7 + src/workerd/io/BUILD.bazel | 12 + src/workerd/io/io-context.h | 4 + src/workerd/io/observer.h | 15 + src/workerd/io/trace-stream.c++ | 955 ++++++++++++++++++ src/workerd/io/trace-stream.h | 82 ++ src/workerd/io/worker-entrypoint.c++ | 6 + src/workerd/io/worker-interface.capnp | 25 + src/workerd/server/BUILD.bazel | 1 + src/workerd/server/server.c++ | 309 +++++- src/workerd/util/BUILD.bazel | 7 + src/workerd/util/autogate.c++ | 2 + src/workerd/util/autogate.h | 1 + src/workerd/util/completion-membrane.h | 66 ++ types/defines/trace.d.ts | 190 ++++ .../generated-snapshot/2021-11-03/index.d.ts | 198 ++++ types/generated-snapshot/2021-11-03/index.ts | 198 ++++ .../generated-snapshot/2022-01-31/index.d.ts | 198 ++++ types/generated-snapshot/2022-01-31/index.ts | 198 ++++ .../generated-snapshot/2022-03-21/index.d.ts | 198 ++++ types/generated-snapshot/2022-03-21/index.ts | 198 ++++ .../generated-snapshot/2022-08-04/index.d.ts | 198 ++++ types/generated-snapshot/2022-08-04/index.ts | 198 ++++ .../generated-snapshot/2022-10-31/index.d.ts | 198 ++++ types/generated-snapshot/2022-10-31/index.ts | 198 ++++ .../generated-snapshot/2022-11-30/index.d.ts | 198 ++++ types/generated-snapshot/2022-11-30/index.ts | 198 ++++ .../generated-snapshot/2023-03-01/index.d.ts | 198 ++++ types/generated-snapshot/2023-03-01/index.ts | 198 ++++ .../generated-snapshot/2023-07-01/index.d.ts | 198 ++++ types/generated-snapshot/2023-07-01/index.ts | 198 ++++ .../experimental/index.d.ts | 198 ++++ .../generated-snapshot/experimental/index.ts | 198 ++++ types/generated-snapshot/oldest/index.d.ts | 198 ++++ types/generated-snapshot/oldest/index.ts | 198 ++++ 37 files changed, 5609 insertions(+), 43 deletions(-) create mode 100644 src/workerd/io/trace-stream.c++ create mode 100644 src/workerd/io/trace-stream.h create mode 100644 src/workerd/util/completion-membrane.h create mode 100644 types/defines/trace.d.ts diff --git a/samples/tail-workers/config.capnp b/samples/tail-workers/config.capnp index bd02f44581c..22972e60e27 100644 --- a/samples/tail-workers/config.capnp +++ b/samples/tail-workers/config.capnp @@ -5,7 +5,10 @@ const tailWorkerExample :Workerd.Config = ( (name = "main", worker = .helloWorld), (name = "log", worker = .logWorker), ], - sockets = [ ( name = "http", address = "*:8080", http = (), service = "main" ) ] + sockets = [ ( name = "http", address = "*:8080", http = (), service = "main" ) ], + autogates = [ + "workerd-autogate-streaming-tail-workers", + ], ); const helloWorld :Workerd.Worker = ( diff --git a/samples/tail-workers/tail.js b/samples/tail-workers/tail.js index f9cd7857ebe..0ccfc9d04b9 100644 --- a/samples/tail-workers/tail.js +++ b/samples/tail-workers/tail.js @@ -6,5 +6,8 @@ export default { // https://developers.cloudflare.com/workers/observability/logs/tail-workers/ tail(traces) { console.log(traces[0].logs); - } + }, + tailStream() { + return {}; + }, }; diff --git a/src/workerd/api/global-scope.h b/src/workerd/api/global-scope.h index 8a3b9f61f51..a8ed3f5f565 100644 --- a/src/workerd/api/global-scope.h +++ b/src/workerd/api/global-scope.h @@ -288,6 +288,10 @@ struct ExportedHandler { jsg::LenientOptional> tail; jsg::LenientOptional> trace; + typedef kj::Promise TailStreamHandler( + jsg::JsObject obj, jsg::Value env, jsg::Optional> ctx); + jsg::LenientOptional> tailStream; + typedef kj::Promise ScheduledHandler(jsg::Ref controller, jsg::Value env, jsg::Optional> ctx); @@ -319,6 +323,7 @@ struct ExportedHandler { JSG_STRUCT(fetch, tail, trace, + tailStream, scheduled, alarm, test, @@ -335,6 +340,7 @@ struct ExportedHandler { type ExportedHandlerFetchHandler = (request: Request>, env: Env, ctx: ExecutionContext) => Response | Promise; type ExportedHandlerTailHandler = (events: TraceItem[], env: Env, ctx: ExecutionContext) => void | Promise; type ExportedHandlerTraceHandler = (traces: TraceItem[], env: Env, ctx: ExecutionContext) => void | Promise; + type ExportedHandlerTailStreamHandler = (event : TailStream.TailEvent, env: Env, ctx: ExecutionContext) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = (controller: ScheduledController, env: Env, ctx: ExecutionContext) => void | Promise; type ExportedHandlerQueueHandler = (batch: MessageBatch, env: Env, ctx: ExecutionContext) => void | Promise; type ExportedHandlerTestHandler = (controller: TestController, env: Env, ctx: ExecutionContext) => void | Promise; @@ -344,6 +350,7 @@ struct ExportedHandler { fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; alarm: never; webSocketMessage: never; diff --git a/src/workerd/io/BUILD.bazel b/src/workerd/io/BUILD.bazel index c1a28cbae78..0a22e2c6ff5 100644 --- a/src/workerd/io/BUILD.bazel +++ b/src/workerd/io/BUILD.bazel @@ -36,6 +36,17 @@ wd_cc_library( ], ) +wd_cc_library( + name = "trace-stream", + srcs = ["trace-stream.c++"], + hdrs = ["trace-stream.h"], + visibility = ["//visibility:public"], + deps = [ + ":io", + "//src/workerd/util:completion-membrane", + ], +) + wd_cc_library( name = "io", # HACK: Currently, the `io` and `api` packages are interdependent. We fold all the sources @@ -106,6 +117,7 @@ wd_cc_library( "//src/workerd/api:url", "//src/workerd/jsg", "//src/workerd/util:autogate", + "//src/workerd/util:completion-membrane", "//src/workerd/util:sqlite", "//src/workerd/util:thread-scopes", "//src/workerd/util:uuid", diff --git a/src/workerd/io/io-context.h b/src/workerd/io/io-context.h index 2bf23326817..7aa3c2687cf 100644 --- a/src/workerd/io/io-context.h +++ b/src/workerd/io/io-context.h @@ -788,6 +788,10 @@ class IoContext final: public kj::Refcounted, private kj::TaskSet::ErrorHandler SpanParent getCurrentTraceSpan(); SpanParent getCurrentUserTraceSpan(); + tracing::InvocationSpanContext& getInvocationSpanContext() { + return getCurrentIncomingRequest().invocationSpanContext; + } + // Returns a builder for recording tracing spans (or a no-op builder if tracing is inactive). // If called while the JS lock is held, uses the trace information from the current async // context, if available. diff --git a/src/workerd/io/observer.h b/src/workerd/io/observer.h index 8c6e741f69d..7239257a565 100644 --- a/src/workerd/io/observer.h +++ b/src/workerd/io/observer.h @@ -18,6 +18,7 @@ namespace workerd { +class IoContext; class WorkerInterface; class LimitEnforcer; class TimerChannel; @@ -127,6 +128,20 @@ class RequestObserver: public kj::Refcounted { return nullptr; } + // If the worker is configured to support streaming tail workers, reportTailEvent + // will forward the given event on to the collection of streaming tail workers + // that are configured with this observer. Otherwise, this is a non-op. + virtual void reportTailEvent(IoContext& ioContext, tracing::TailEvent::Event&& event) { + reportTailEvent(ioContext, [event = kj::mv(event)]() mutable { return kj::mv(event); }); + } + + // If the worker is configured to support streaming tail workers, reportTailEvent + // will forward the event returned by the callback on to the collection of streaming + // fail workers that are configured with this observer. The callback will only be + // invoked if there are tail workers. + virtual void reportTailEvent( + IoContext& ioContext, kj::FunctionParam fn) {} + virtual kj::Own addedContextTask() { return kj::Own(); } diff --git a/src/workerd/io/trace-stream.c++ b/src/workerd/io/trace-stream.c++ new file mode 100644 index 00000000000..14b2db3c0a1 --- /dev/null +++ b/src/workerd/io/trace-stream.c++ @@ -0,0 +1,955 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace workerd::tracing { +namespace { + +#define STRS(V) \ + V(ALARM, "alarm") \ + V(ATTACHMENT, "attachment") \ + V(ATTRIBUTE, "attribute") \ + V(BATCHSIZE, "batchSize") \ + V(CANCELED, "canceled") \ + V(CHANNEL, "channel") \ + V(CFJSON, "cfJson") \ + V(CLOSE, "close") \ + V(CODE, "code") \ + V(CPUTIME, "cpuTime") \ + V(CRON, "cron") \ + V(CUSTOM, "custom") \ + V(DAEMONDOWN, "daemonDown") \ + V(DEBUG, "debug") \ + V(DIAGNOSTICCHANNEL, "diagnosticChannel") \ + V(DISPATCHNAMESPACE, "dispatchNamespace") \ + V(EMAIL, "email") \ + V(ENTRYPOINT, "entrypoint") \ + V(ERROR, "error") \ + V(EVENT, "event") \ + V(EXCEEDEDCPU, "exceededCpu") \ + V(EXCEEDEDMEMORY, "exceededMemory") \ + V(EXCEPTION, "exception") \ + V(FETCH, "fetch") \ + V(HEADERS, "headers") \ + V(HIBERNATABLEWEBSOCKET, "hibernatableWebSocket") \ + V(HIBERNATE, "hibernate") \ + V(ID, "id") \ + V(INFO, "info") \ + V(INVOCATIONID, "invocationId") \ + V(JSRPC, "jsrpc") \ + V(KILLSWITCH, "killSwitch") \ + V(LABEL, "label") \ + V(LEVEL, "level") \ + V(LINK, "link") \ + V(LOADSHED, "loadShed") \ + V(LOG, "log") \ + V(MAILFROM, "mailFrom") \ + V(MESSAGE, "message") \ + V(METHOD, "method") \ + V(METHODNAME, "methodName") \ + V(NAME, "name") \ + V(OK, "ok") \ + V(ONSET, "onset") \ + V(OP, "op") \ + V(OUTCOME, "outcome") \ + V(QUEUE, "queue") \ + V(QUEUENAME, "queueName") \ + V(RAWSIZE, "rawSize") \ + V(RCPTTO, "rcptTo") \ + V(RESPONSESTREAMDISCONNECTED, "responseStreamDisconnected") \ + V(RESUME, "resume") \ + V(RETURN, "return") \ + V(SCHEDULED, "scheduled") \ + V(SCHEDULEDTIME, "scheduledTime") \ + V(SCRIPTNAME, "scriptName") \ + V(SCRIPTNOTFOUND, "scriptNotFound") \ + V(SCRIPTTAGS, "scriptTags") \ + V(SCRIPTVERSION, "scriptVersion") \ + V(SEQUENCE, "sequence") \ + V(SPANCLOSE, "spanClose") \ + V(SPANID, "spanId") \ + V(SPANOPEN, "spanOpen") \ + V(STACK, "stack") \ + V(STATUSCODE, "statusCode") \ + V(TAG, "tag") \ + V(TIMESTAMP, "timestamp") \ + V(TRACEID, "traceId") \ + V(TRACE, "trace") \ + V(TRACES, "traces") \ + V(TRIGGER, "trigger") \ + V(TYPE, "type") \ + V(UNKNOWN, "unknown") \ + V(URL, "url") \ + V(VALUE, "value") \ + V(WALLTIME, "wallTime") \ + V(WARN, "warn") \ + V(WASCLEAN, "wasClean") + +#define V(N, L) constexpr kj::StringPtr N##_STR = L##_kj; +STRS(V) +#undef STRS + +// Utility that prevents creating duplicate JS strings while serializing a tail event. +class StringCache final { + public: + StringCache() = default; + KJ_DISALLOW_COPY_AND_MOVE(StringCache); + + jsg::JsValue get(jsg::Lock& js, kj::StringPtr value) { + return cache + .findOrCreate(value, [&]() -> decltype(cache)::Entry { + return {value, jsg::JsRef(js, js.strIntern(value))}; + }).getHandle(js); + } + + private: + kj::HashMap> cache; +}; + +// Why ToJS(...) functions and not JSG_STRUCT? Good question. The various tracing:* +// types are defined in the "trace" bazel target which currently does not depend on +// jsg in any way. These also represent the internal API of these types which doesn't +// really match exactly what we want to expose to users. In order to use JSG_STRUCT +// we would either need to make the "trace" target depend on "jsg", which seems a bit +// wasteful and unnecessary, or we'd need to define wrapper structs that use JSG_STRUCT +// which also seems wasteful and unnecessary. We also don't need the type mapping for +// these structs to be bidirectional. So, instead, let's just do the simple easy thing +// and define a set of serializers to these types. + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Attribute::Value& value) { + KJ_SWITCH_ONEOF(value) { + KJ_CASE_ONEOF(str, kj::String) { + return js.str(str); + } + KJ_CASE_ONEOF(b, bool) { + return js.boolean(b); + } + KJ_CASE_ONEOF(d, double) { + return js.num(d); + } + KJ_CASE_ONEOF(i, int32_t) { + return js.num(i); + } + } + KJ_UNREACHABLE; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Attribute& attribute, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, ATTRIBUTE_STR)); + obj.set(js, NAME_STR, cache.get(js, attribute.name)); + + if (attribute.value.size() == 1) { + obj.set(js, VALUE_STR, ToJs(js, attribute.value[0])); + } else { + auto values = KJ_MAP(val, attribute.value) { return ToJs(js, val); }; + obj.set(js, VALUE_STR, js.arr(values)); + } + + return obj; +} + +jsg::JsValue ToJs( + jsg::Lock& js, kj::ArrayPtr attributes, StringCache& cache) { + auto attrs = KJ_MAP(attr, attributes) { return ToJs(js, attr, cache); }; + return js.arr(attrs); +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::FetchResponseInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, FETCH_STR)); + obj.set(js, STATUSCODE_STR, js.num(info.statusCode)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::FetchEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, FETCH_STR)); + obj.set(js, METHOD_STR, cache.get(js, kj::str(info.method))); + obj.set(js, URL_STR, js.str(info.url)); + obj.set(js, CFJSON_STR, js.str(info.cfJson)); + + auto ToJs = [](jsg::Lock& js, const tracing::FetchEventInfo::Header& header, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, NAME_STR, cache.get(js, header.name)); + obj.set(js, VALUE_STR, js.str(header.value)); + return obj; + }; + + auto headers = KJ_MAP(header, info.headers) -> jsg::JsValue { return ToJs(js, header, cache); }; + obj.set(js, HEADERS_STR, js.arr(headers)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::JsRpcEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, JSRPC_STR)); + obj.set(js, METHODNAME_STR, cache.get(js, info.methodName)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::ScheduledEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, SCHEDULED_STR)); + obj.set(js, SCHEDULEDTIME_STR, js.date(info.scheduledTime)); + obj.set(js, CRON_STR, js.str(info.cron)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::AlarmEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, ALARM_STR)); + obj.set(js, SCHEDULEDTIME_STR, js.date(info.scheduledTime)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::QueueEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, QUEUE_STR)); + obj.set(js, QUEUENAME_STR, js.str(info.queueName)); + obj.set(js, BATCHSIZE_STR, js.num(info.batchSize)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::EmailEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, EMAIL_STR)); + obj.set(js, MAILFROM_STR, js.str(info.mailFrom)); + obj.set(js, RCPTTO_STR, js.str(info.rcptTo)); + obj.set(js, RAWSIZE_STR, js.num(info.rawSize)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::TraceEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, TRACE_STR)); + + auto names = KJ_MAP(trace, info.traces) -> jsg::JsValue { + KJ_IF_SOME(name, trace.scriptName) { + return js.str(name); + } + return js.null(); + }; + obj.set(js, TRACES_STR, js.arr(names)); + + return obj; +} + +jsg::JsValue ToJs( + jsg::Lock& js, const tracing::HibernatableWebSocketEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, HIBERNATABLEWEBSOCKET_STR)); + + KJ_SWITCH_ONEOF(info.type) { + KJ_CASE_ONEOF(message, tracing::HibernatableWebSocketEventInfo::Message) { + auto mobj = js.obj(); + mobj.set(js, TYPE_STR, cache.get(js, MESSAGE_STR)); + obj.set(js, INFO_STR, mobj); + } + KJ_CASE_ONEOF(error, tracing::HibernatableWebSocketEventInfo::Error) { + auto mobj = js.obj(); + mobj.set(js, TYPE_STR, cache.get(js, ERROR_STR)); + obj.set(js, INFO_STR, mobj); + } + KJ_CASE_ONEOF(close, tracing::HibernatableWebSocketEventInfo::Close) { + auto mobj = js.obj(); + mobj.set(js, TYPE_STR, cache.get(js, CLOSE_STR)); + mobj.set(js, CODE_STR, js.num(close.code)); + mobj.set(js, WASCLEAN_STR, js.boolean(close.wasClean)); + obj.set(js, INFO_STR, mobj); + } + } + + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Resume& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, RESUME_STR)); + + KJ_IF_SOME(attachment, info.attachment) { + jsg::Serializer::Released data{ + .data = kj::heapArray(attachment), + }; + jsg::Deserializer deser(js, data); + obj.set(js, ATTACHMENT_STR, deser.readValue(js)); + } + + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::CustomEventInfo& info, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, CUSTOM_STR)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const EventOutcome& outcome, StringCache& cache) { + switch (outcome) { + case EventOutcome::OK: + return cache.get(js, OK_STR); + case EventOutcome::CANCELED: + return cache.get(js, CANCELED_STR); + case EventOutcome::EXCEPTION: + return cache.get(js, EXCEPTION_STR); + case EventOutcome::KILL_SWITCH: + return cache.get(js, KILLSWITCH_STR); + case EventOutcome::DAEMON_DOWN: + return cache.get(js, DAEMONDOWN_STR); + case EventOutcome::EXCEEDED_CPU: + return cache.get(js, EXCEEDEDCPU_STR); + case EventOutcome::EXCEEDED_MEMORY: + return cache.get(js, EXCEEDEDMEMORY_STR); + case EventOutcome::LOAD_SHED: + return cache.get(js, LOADSHED_STR); + case EventOutcome::RESPONSE_STREAM_DISCONNECTED: + return cache.get(js, RESPONSESTREAMDISCONNECTED_STR); + case EventOutcome::SCRIPT_NOT_FOUND: + return cache.get(js, SCRIPTNOTFOUND_STR); + case EventOutcome::UNKNOWN: + return cache.get(js, UNKNOWN_STR); + } + KJ_UNREACHABLE; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Onset& onset, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, ONSET_STR)); + + KJ_IF_SOME(ns, onset.workerInfo.dispatchNamespace) { + obj.set(js, DISPATCHNAMESPACE_STR, js.str(ns)); + } + KJ_IF_SOME(entrypoint, onset.workerInfo.entrypoint) { + obj.set(js, ENTRYPOINT_STR, js.str(entrypoint)); + } + KJ_IF_SOME(name, onset.workerInfo.scriptName) { + obj.set(js, SCRIPTNAME_STR, js.str(name)); + } + KJ_IF_SOME(tags, onset.workerInfo.scriptTags) { + auto vals = KJ_MAP(tag, tags) -> jsg::JsValue { return js.str(tag); }; + obj.set(js, SCRIPTTAGS_STR, js.arr(vals)); + } + KJ_IF_SOME(version, onset.workerInfo.scriptVersion) { + auto vobj = js.obj(); + auto id = version->getId(); + KJ_IF_SOME(uuid, UUID::fromUpperLower(id.getUpper(), id.getLower())) { + vobj.set(js, ID_STR, js.str(uuid.toString())); + } + if (version->hasTag()) { + vobj.set(js, TAG_STR, js.str(version->getTag())); + } + if (version->hasMessage()) { + vobj.set(js, MESSAGE_STR, js.str(version->getMessage())); + } + obj.set(js, SCRIPTVERSION_STR, vobj); + } + + KJ_IF_SOME(trigger, onset.trigger) { + auto tobj = js.obj(); + tobj.set(js, TRACEID_STR, js.str(trigger.traceId.toGoString())); + tobj.set(js, INVOCATIONID_STR, js.str(trigger.invocationId.toGoString())); + tobj.set(js, SPANID_STR, js.str(trigger.spanId.toGoString())); + obj.set(js, TRIGGER_STR, tobj); + } + + KJ_SWITCH_ONEOF(onset.info) { + KJ_CASE_ONEOF(fetch, tracing::FetchEventInfo) { + obj.set(js, INFO_STR, ToJs(js, fetch, cache)); + } + KJ_CASE_ONEOF(jsrpc, tracing::JsRpcEventInfo) { + obj.set(js, INFO_STR, ToJs(js, jsrpc, cache)); + } + KJ_CASE_ONEOF(scheduled, tracing::ScheduledEventInfo) { + obj.set(js, INFO_STR, ToJs(js, scheduled, cache)); + } + KJ_CASE_ONEOF(alarm, tracing::AlarmEventInfo) { + obj.set(js, INFO_STR, ToJs(js, alarm, cache)); + } + KJ_CASE_ONEOF(queue, tracing::QueueEventInfo) { + obj.set(js, INFO_STR, ToJs(js, queue, cache)); + } + KJ_CASE_ONEOF(email, tracing::EmailEventInfo) { + obj.set(js, INFO_STR, ToJs(js, email, cache)); + } + KJ_CASE_ONEOF(trace, tracing::TraceEventInfo) { + obj.set(js, INFO_STR, ToJs(js, trace, cache)); + } + KJ_CASE_ONEOF(hws, tracing::HibernatableWebSocketEventInfo) { + obj.set(js, INFO_STR, ToJs(js, hws, cache)); + } + KJ_CASE_ONEOF(resume, tracing::Resume) { + obj.set(js, INFO_STR, ToJs(js, resume, cache)); + } + KJ_CASE_ONEOF(custom, tracing::CustomEventInfo) { + obj.set(js, INFO_STR, ToJs(js, custom, cache)); + } + } + + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Outcome& outcome, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, OUTCOME_STR)); + obj.set(js, OUTCOME_STR, ToJs(js, outcome.outcome, cache)); + + double cpuTime = outcome.cpuTime / kj::MILLISECONDS; + double wallTime = outcome.wallTime / kj::MILLISECONDS; + + obj.set(js, CPUTIME_STR, js.num(cpuTime)); + obj.set(js, WALLTIME_STR, js.num(wallTime)); + + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Hibernate& hibernate, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, HIBERNATE_STR)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::SpanOpen& spanOpen, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, SPANOPEN_STR)); + KJ_IF_SOME(op, spanOpen.operationName) { + obj.set(js, OP_STR, js.str(op)); + } + KJ_IF_SOME(info, spanOpen.info) { + KJ_SWITCH_ONEOF(info) { + KJ_CASE_ONEOF(fetch, tracing::FetchEventInfo) { + obj.set(js, INFO_STR, ToJs(js, fetch, cache)); + } + KJ_CASE_ONEOF(jsrpc, tracing::JsRpcEventInfo) { + obj.set(js, INFO_STR, ToJs(js, jsrpc, cache)); + } + KJ_CASE_ONEOF(custom, tracing::CustomInfo) { + obj.set(js, INFO_STR, ToJs(js, custom.asPtr(), cache)); + } + } + } + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::SpanClose& spanClose, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, SPANCLOSE_STR)); + obj.set(js, OUTCOME_STR, ToJs(js, spanClose.outcome, cache)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::DiagnosticChannelEvent& dce, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, DIAGNOSTICCHANNEL_STR)); + obj.set(js, CHANNEL_STR, cache.get(js, dce.channel)); + jsg::Serializer::Released released{ + .data = kj::heapArray(dce.message), + }; + jsg::Deserializer deser(js, released); + obj.set(js, MESSAGE_STR, deser.readValue(js)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Exception& ex, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, EXCEPTION_STR)); + obj.set(js, NAME_STR, cache.get(js, ex.name)); + obj.set(js, MESSAGE_STR, js.str(ex.message)); + KJ_IF_SOME(stack, ex.stack) { + obj.set(js, STACK_STR, js.str(stack)); + } + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const LogLevel& level, StringCache& cache) { + switch (level) { + case LogLevel::DEBUG_: + return cache.get(js, DEBUG_STR); + case LogLevel::ERROR: + return cache.get(js, ERROR_STR); + case LogLevel::INFO: + return cache.get(js, INFO_STR); + case LogLevel::LOG: + return cache.get(js, LOG_STR); + case LogLevel::WARN: + return cache.get(js, WARN_STR); + } + KJ_UNREACHABLE; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Log& log, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, LOG_STR)); + obj.set(js, LEVEL_STR, ToJs(js, log.logLevel, cache)); + obj.set(js, MESSAGE_STR, js.str(log.message)); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Return& ret, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, RETURN_STR)); + + KJ_IF_SOME(info, ret.info) { + KJ_SWITCH_ONEOF(info) { + KJ_CASE_ONEOF(fetch, tracing::FetchResponseInfo) { + obj.set(js, INFO_STR, ToJs(js, fetch, cache)); + } + KJ_CASE_ONEOF(custom, tracing::CustomInfo) { + obj.set(js, INFO_STR, ToJs(js, custom.asPtr(), cache)); + } + } + } + + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::Link& link, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TYPE_STR, cache.get(js, LINK_STR)); + KJ_IF_SOME(label, link.label) { + obj.set(js, LABEL_STR, js.str(label)); + } + obj.set(js, TRACEID_STR, js.str(link.traceId.toGoString())); + obj.set(js, INVOCATIONID_STR, js.str(link.invocationId.toGoString())); + obj.set(js, SPANID_STR, js.str(link.spanId.toGoString())); + return obj; +} + +jsg::JsValue ToJs(jsg::Lock& js, const tracing::TailEvent& event, StringCache& cache) { + auto obj = js.obj(); + obj.set(js, TRACEID_STR, js.str(event.traceId.toGoString())); + obj.set(js, INVOCATIONID_STR, js.str(event.invocationId.toGoString())); + obj.set(js, SPANID_STR, js.str(event.spanId.toGoString())); + obj.set(js, TIMESTAMP_STR, js.date(event.timestamp)); + obj.set(js, SEQUENCE_STR, js.num(event.sequence)); + + KJ_SWITCH_ONEOF(event.event) { + KJ_CASE_ONEOF(onset, tracing::Onset) { + obj.set(js, EVENT_STR, ToJs(js, onset, cache)); + } + KJ_CASE_ONEOF(outcome, tracing::Outcome) { + obj.set(js, EVENT_STR, ToJs(js, outcome, cache)); + } + KJ_CASE_ONEOF(hibernate, tracing::Hibernate) { + obj.set(js, EVENT_STR, ToJs(js, hibernate, cache)); + } + KJ_CASE_ONEOF(spanOpen, tracing::SpanOpen) { + obj.set(js, EVENT_STR, ToJs(js, spanOpen, cache)); + } + KJ_CASE_ONEOF(spanClose, tracing::SpanClose) { + obj.set(js, EVENT_STR, ToJs(js, spanClose, cache)); + } + KJ_CASE_ONEOF(mark, tracing::Mark) { + KJ_SWITCH_ONEOF(mark) { + KJ_CASE_ONEOF(de, tracing::DiagnosticChannelEvent) { + obj.set(js, EVENT_STR, ToJs(js, de, cache)); + } + KJ_CASE_ONEOF(ex, tracing::Exception) { + obj.set(js, EVENT_STR, ToJs(js, ex, cache)); + } + KJ_CASE_ONEOF(log, tracing::Log) { + obj.set(js, EVENT_STR, ToJs(js, log, cache)); + } + KJ_CASE_ONEOF(ret, tracing::Return) { + obj.set(js, EVENT_STR, ToJs(js, ret, cache)); + } + KJ_CASE_ONEOF(link, tracing::Link) { + obj.set(js, EVENT_STR, ToJs(js, link, cache)); + } + KJ_CASE_ONEOF(attrs, kj::Array) { + obj.set(js, EVENT_STR, ToJs(js, attrs, cache)); + } + } + } + } + + return obj; +} + +// See the documentation for the identically named class in worker-rpc.c++ for details. +// TODO(cleanup): Combine this and the worker-rpc.c++ class into a single utility. +class ServerTopLevelMembrane final: public capnp::MembranePolicy, public kj::Refcounted { + public: + explicit ServerTopLevelMembrane(kj::Own> doneFulfiller) + : doneFulfiller(kj::mv(doneFulfiller)) {} + ~ServerTopLevelMembrane() noexcept(false) { + KJ_IF_SOME(f, doneFulfiller) { + f->reject( + KJ_EXCEPTION(DISCONNECTED, "Tail stream session canceled without handling any events.")); + } + } + + kj::Maybe inboundCall( + uint64_t interfaceId, uint16_t methodId, capnp::Capability::Client target) override { + auto f = kj::mv(JSG_REQUIRE_NONNULL( + doneFulfiller, Error, "Only one tailStream method call is allowed on this object.")); + doneFulfiller = kj::none; + return capnp::membrane(kj::mv(target), kj::refcounted(kj::mv(f))); + } + + kj::Maybe outboundCall( + uint64_t interfaceId, uint16_t methodId, capnp::Capability::Client target) override { + KJ_FAIL_ASSERT("ServerTopLevelMembrane shouldn't have outgoing capabilities"); + } + + kj::Own addRef() override { + return kj::addRef(*this); + } + + private: + kj::Maybe>> doneFulfiller; +}; + +class TailStreamTargetBase: public rpc::TailStreamTarget::Server { + public: + TailStreamTargetBase(IoContext& ioContext): weakIoContext(ioContext.getWeakRef()) {} + KJ_DISALLOW_COPY_AND_MOVE(TailStreamTargetBase); + virtual ~TailStreamTargetBase() = default; + + virtual kj::Promise runImpl(Worker::Lock& lock, + IoContext& ioContext, + kj::ArrayPtr events, + rpc::TailStreamTarget::TailStreamResults::Builder results) = 0; + + kj::Promise report(ReportContext reportContext) override { + IoContext& ioContext = JSG_REQUIRE_NONNULL(weakIoContext->tryGet(), Error, + "The destination object for this tail session no longer exists."); + + ioContext.getLimitEnforcer().topUpActor(); + + auto ownReportContext = capnp::CallContextHook::from(reportContext).addRef(); + + auto promise = + ioContext + .run([this, &ioContext, reportContext, ownReportContext = kj::mv(ownReportContext)]( + Worker::Lock& lock) mutable -> kj::Promise { + auto params = reportContext.getParams(); + KJ_ASSERT(params.hasEvents(), "Events are required."); + auto eventReaders = params.getEvents(); + kj::Vector events(eventReaders.size()); + for (auto reader: eventReaders) { + events.add(tracing::TailEvent(reader)); + } + auto result = runImpl(lock, ioContext, events.releaseAsArray(), reportContext.initResults()); + + if (ioContext.hasOutputGate()) { + return result.then([weakIoContext = weakIoContext->addRef()]() mutable { + return KJ_REQUIRE_NONNULL(weakIoContext->tryGet()).waitForOutputLocks(); + }); + } else { + return kj::mv(result); + } + }).catch_([](kj::Exception&& e) { + if (jsg::isTunneledException(e.getDescription())) { + auto description = jsg::stripRemoteExceptionPrefix(e.getDescription()); + if (!description.startsWith("remote.")) { + e.setDescription(kj::str("remote.", description)); + } + } + kj::throwFatalException(kj::mv(e)); + }); + + auto paf = kj::newPromiseAndFulfiller(); + promise = promise.then([&fulfiller = *paf.fulfiller]() { fulfiller.fulfill(); }, + [&fulfiller = *paf.fulfiller](kj::Exception&& e) { fulfiller.reject(kj::mv(e)); }); + promise = promise.attach(kj::defer([fulfiller = kj::mv(paf.fulfiller)]() mutable { + if (fulfiller->isWaiting()) { + fulfiller->reject(JSG_KJ_EXCEPTION(FAILED, Error, + "The destination execution context for this tail session was canceled while the " + "call was still running.")); + } + })); + ioContext.addTask(kj::mv(promise)); + + return kj::mv(paf.promise); + } + + private: + kj::Own weakIoContext; +}; + +// Returns the name of the handler function for this type of event. +kj::Maybe getHandlerName(const tracing::TailEvent& event) { + KJ_SWITCH_ONEOF(event.event) { + KJ_CASE_ONEOF(_, tracing::Onset) { + return ONSET_STR; + } + KJ_CASE_ONEOF(_, tracing::Outcome) { + return OUTCOME_STR; + } + KJ_CASE_ONEOF(_, tracing::Hibernate) { + return HIBERNATE_STR; + } + KJ_CASE_ONEOF(_, tracing::SpanOpen) { + return SPANOPEN_STR; + } + KJ_CASE_ONEOF(_, tracing::SpanClose) { + return SPANCLOSE_STR; + } + KJ_CASE_ONEOF(mark, tracing::Mark) { + KJ_SWITCH_ONEOF(mark) { + KJ_CASE_ONEOF(_, tracing::DiagnosticChannelEvent) { + return DIAGNOSTICCHANNEL_STR; + } + KJ_CASE_ONEOF(_, tracing::Exception) { + return EXCEPTION_STR; + } + KJ_CASE_ONEOF(_, tracing::Log) { + return LOG_STR; + } + KJ_CASE_ONEOF(_, tracing::Return) { + return RETURN_STR; + } + KJ_CASE_ONEOF(_, tracing::Link) { + return LINK_STR; + } + KJ_CASE_ONEOF(_, kj::Array) { + return ATTRIBUTE_STR; + } + } + } + } + return kj::none; +} + +// The TailStreamEntrypoint class handles the initial onset event and the determination +// of whether additional events should be handled in this stream. If a handler is +// returned then a capability to access the TailStreamHandler is returned. This class +// takes over and handles the remaining events in the stream. +class TailStreamHandler final: public TailStreamTargetBase { + public: + TailStreamHandler(IoContext& ioContext, jsg::JsRef handler) + : TailStreamTargetBase(ioContext), + handler(kj::mv(handler)) {} + + kj::Promise runImpl(Worker::Lock& lock, + IoContext& ioContext, + kj::ArrayPtr events, + rpc::TailStreamTarget::TailStreamResults::Builder results) { + jsg::Lock& js = lock; + + if (events.size() == 0) return kj::READY_NOW; + + // Take the received set of events and dispatch them to the correct handler. + + v8::Local h = handler.getHandle(js); + v8::LocalVector returnValues(js.v8Isolate, events.size()); + StringCache stringCache; + + if (h->IsFunction()) { + // If the handler is a function, then we'll just pass all of the events to that + // function. If the function returns a promise and there are multiple events we + // will not wait for each promise to resolve before calling the next iteration. + // But we will wait for all promises to settle before returning the resolved + // kj promise. + auto fn = h.As(); + for (auto& event: events) { + v8::Local eventObj = ToJs(js, event, stringCache); + returnValues.push_back(jsg::check(fn->Call(js.v8Context(), h, 1, &eventObj))); + } + } else { + // If the handler is an object, then we need to know what kind of events + // we have and look for a specific handler function for each. + KJ_ASSERT(h->IsObject()); + jsg::JsObject obj = jsg::JsObject(h.As()); + for (auto& event: events) { + // It is technically an error not to have a handler name here as we shouldn't + // be reporting any events we don't know! But, there's no reason to treat it + // as an error here. + KJ_IF_SOME(name, getHandlerName(event)) { + v8::Local val = obj.get(js, name); + // If the value is not a function, we'll ignore it entirely. + if (val->IsFunction()) { + auto fn = val.As(); + v8::Local eventObj = ToJs(js, event, stringCache); + returnValues.push_back(jsg::check(fn->Call(js.v8Context(), h, 1, &eventObj))); + } + } + } + } + + // We want the equivalent behavior to Promise.all([...]) here but v8 does not + // give us a C++ equivalent of Promise.all([...]) so we need to approximate it. + // We do so by chaining all of the promises together. + kj::Maybe> promise; + for (auto& val: returnValues) { + KJ_IF_SOME(p, promise) { + promise = p.then(js, + [p = js.toPromise(val).whenResolved(js)](jsg::Lock& js) mutable { return kj::mv(p); }); + } else { + promise = js.toPromise(val).whenResolved(js); + } + } + + KJ_IF_SOME(p, promise) { + return ioContext.awaitJs(js, kj::mv(p)); + } + return kj::READY_NOW; + } + + private: + jsg::JsRef handler; +}; + +// The TailStreamEndpoint class handles the initial onset event and the determination +// or whether additional events should be handled in this stream. +class TailStreamEntrypoint final: public TailStreamTargetBase { + public: + TailStreamEntrypoint(IoContext& ioContext, Frankenvalue props) + : TailStreamTargetBase(ioContext), + props(kj::mv(props)) {} + + kj::Promise runImpl(Worker::Lock& lock, + IoContext& ioContext, + kj::ArrayPtr events, + rpc::TailStreamTarget::TailStreamResults::Builder results) { + jsg::Lock& js = lock; + // There should be only a single onset event in this one. + KJ_ASSERT(events.size() == 1 && events[0].event.is(), + "Expected only a single onset event"); + auto& event = events[0]; + + auto handler = KJ_REQUIRE_NONNULL( + lock.getExportedHandler("default"_kj, kj::mv(props), ioContext.getActor()), + "Failed to get handler to worker."); + StringCache stringCache; + + auto target = jsg::JsObject(handler->self.getHandle(lock)); + v8::Local maybeFn = target.get(lock, "tailStream"_kj); + if (!maybeFn->IsFunction()) { + // If there's no actual tailStream handler we will emit a warning for the user + // then immediately return. + ioContext.logWarningOnce("A worker configured to act as a streaming tail worker does " + "not export a tailStream() handler."); + return kj::READY_NOW; + } + + v8::Local fn = maybeFn.As(); + + v8::Local obj = ToJs(js, event, stringCache); + auto result = jsg::check(fn->Call(js.v8Context(), target, 1, &obj)); + + return ioContext.awaitJs(js, + js.toPromise(result).then(js, + ioContext.addFunctor([&results, &ioContext](jsg::Lock& js, jsg::Value value) { + // The value here can be one of a function, an object, or undefined. + // Any value other than these will result in a warning but will otherwise + // be treated like undefined. + // + // If a function or object is returned, we will pass a new capability + // back to the caller that can be used to keep pushing events. + // + auto handle = value.getHandle(js); + if (handle->IsFunction() || handle->IsObject()) { + // Sweet! We'll take the handle and pass it off to a new TailStreamHandler + // that we will use to initialize a new capability to return to the user. + results.setPipeline(rpc::TailStreamTarget::Client( + kj::heap(ioContext, jsg::JsRef(js, jsg::JsValue(handle))))); + return; + } + + if (!handle->IsUndefined()) { + ioContext.logWarningOnce( + "tailStream() handler returned an unusable value. " + "The tailStream() handler is expected to return either a function, an " + "object, or undefined."); + } + }), + ioContext.addFunctor( + [](jsg::Lock& js, jsg::Value&& error) { js.throwException(kj::mv(error)); }))); + } + + private: + Frankenvalue props; +}; +} // namespace + +kj::Promise TailStreamCustomEventImpl::run( + kj::Own incomingRequest, + kj::Maybe entrypointName, + Frankenvalue props, + kj::TaskSet& waitUntilTasks) { + IoContext& ioContext = incomingRequest->getContext(); + incomingRequest->delivered(); + + auto [donePromise, doneFulfiller] = kj::newPromiseAndFulfiller(); + capFulfiller->fulfill(capnp::membrane(kj::heap(ioContext, kj::mv(props)), + kj::refcounted(kj::mv(doneFulfiller)))); + + KJ_DEFER({ + // waitUntil() should allow extending execution on the server side even when the client + // disconnects. + waitUntilTasks.add(incomingRequest->drain().attach(kj::mv(incomingRequest))); + }); + + // `donePromise` resolves once there are no longer any capabilities pointing between the client + // and server as part of this session. + co_await donePromise.exclusiveJoin(ioContext.onAbort()); + + co_return WorkerInterface::CustomEvent::Result{.outcome = EventOutcome::OK}; +} + +kj::Promise TailStreamCustomEventImpl::sendRpc( + capnp::HttpOverCapnpFactory& httpOverCapnpFactory, + capnp::ByteStreamFactory& byteStreamFactory, + rpc::EventDispatcher::Client dispatcher) { + auto revokePaf = kj::newPromiseAndFulfiller(); + + KJ_DEFER({ + if (revokePaf.fulfiller->isWaiting()) { + revokePaf.fulfiller->reject(KJ_EXCEPTION(DISCONNECTED, "Streaming tail session canceled")); + } + }); + + auto req = dispatcher.tailStreamSessionRequest(); + auto sent = req.send(); + + rpc::TailStreamTarget::Client cap = sent.getTopLevel(); + + cap = capnp::membrane(kj::mv(cap), kj::refcounted(kj::mv(revokePaf.promise))); + + auto completionPaf = kj::newPromiseAndFulfiller(); + cap = capnp::membrane( + kj::mv(cap), kj::refcounted(kj::mv(completionPaf.fulfiller))); + + this->capFulfiller->fulfill(kj::mv(cap)); + + try { + co_await sent.ignoreResult().exclusiveJoin(kj::mv(completionPaf.promise)); + } catch (...) { + auto e = kj::getCaughtExceptionAsKj(); + if (revokePaf.fulfiller->isWaiting()) { + revokePaf.fulfiller->reject(kj::cp(e)); + } + kj::throwFatalException(kj::mv(e)); + } + + co_return WorkerInterface::CustomEvent::Result{.outcome = EventOutcome::OK}; +} + +tracing::TailStreamWriter::TailStreamWriter(Reporter reporter): state(State(kj::mv(reporter))) {} + +void tracing::TailStreamWriter::report(IoContext& ioContext, TailEvent::Event&& event) { + auto& s = KJ_UNWRAP_OR_RETURN(state); + bool ending = event.tryGet() != kj::none || + event.tryGet() != kj::none; + KJ_DEFER({ + if (ending) state = kj::none; + }); + if (event.tryGet() != kj::none) { + KJ_ASSERT(!s.onsetSeen, "Tail stream onset already provided"); + s.onsetSeen = true; + } + tracing::TailEvent tailEvent( + ioContext.getInvocationSpanContext(), ioContext.now(), s.sequence++, kj::mv(event)); + + // If the reporter returns false, then we will treat it as a close signal. + ending = !s.reporter(ioContext, kj::mv(tailEvent)); +} + +} // namespace workerd::tracing diff --git a/src/workerd/io/trace-stream.h b/src/workerd/io/trace-stream.h new file mode 100644 index 00000000000..55460db2a0f --- /dev/null +++ b/src/workerd/io/trace-stream.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include + +namespace workerd::tracing { + +// A WorkerInterface::CustomEvent implementation used to deliver streaming tail +// events to a tail worker. +class TailStreamCustomEventImpl final: public WorkerInterface::CustomEvent { + public: + TailStreamCustomEventImpl(uint16_t typeId = TYPE, + kj::PromiseFulfillerPair paf = + kj::newPromiseAndFulfiller()) + : capFulfiller(kj::mv(paf.fulfiller)), + clientCap(kj::mv(paf.promise)), + typeId(typeId) {} + + kj::Promise run(kj::Own incomingRequest, + kj::Maybe entrypointName, + Frankenvalue props, + kj::TaskSet& waitUntilTasks) override; + + kj::Promise sendRpc(capnp::HttpOverCapnpFactory& httpOverCapnpFactory, + capnp::ByteStreamFactory& byteStreamFactory, + rpc::EventDispatcher::Client dispatcher) override; + + kj::Promise notSupported() override { + JSG_FAIL_REQUIRE(TypeError, "The receiver is not a tail stream"); + } + + uint16_t getType() override { + return typeId; + } + + // TODO(streaming-tail-workers): Specify the correct type as specified in the + // internal capnp definition. + static constexpr uint16_t TYPE = 11; + + rpc::TailStreamTarget::Client getCap() { + auto result = kj::mv(KJ_ASSERT_NONNULL(clientCap, "can only call getCap() once")); + clientCap = kj::none; + return result; + } + + private: + kj::Own> capFulfiller; + kj::Maybe clientCap; + uint16_t typeId; +}; + +// A utility class that receives tracing events and generates/reports TailEvents. +class TailStreamWriter final { + public: + // If the Reporter returns false, then the writer should transition into a + // closed state. + using Reporter = kj::Function; + + TailStreamWriter(Reporter reporter); + KJ_DISALLOW_COPY_AND_MOVE(TailStreamWriter); + + void report(IoContext& ioContext, TailEvent::Event&& event); + inline void report(IoContext& ioContext, Mark&& event) { + report(ioContext, TailEvent::Event(kj::mv(event))); + } + + inline bool isClosed() const { + return state == kj::none; + } + + private: + struct State { + Reporter reporter; + uint32_t sequence = 0; + bool onsetSeen = false; + State(Reporter reporter): reporter(kj::mv(reporter)) {} + }; + kj::Maybe state; +}; + +} // namespace workerd::tracing diff --git a/src/workerd/io/worker-entrypoint.c++ b/src/workerd/io/worker-entrypoint.c++ index 83c7c5aed8d..571e9c85ff6 100644 --- a/src/workerd/io/worker-entrypoint.c++ +++ b/src/workerd/io/worker-entrypoint.c++ @@ -279,6 +279,12 @@ kj::Promise WorkerEntrypoint::request(kj::HttpMethod method, tracing::FetchEventInfo(method, kj::str(url), kj::mv(cfJson), kj::mv(traceHeadersArray))); } + // TODO(streaming-tail-workers): Instrument properly + context.getMetrics().reportTailEvent(context, [&] { + return tracing::Onset(tracing::FetchEventInfo(method, kj::str(url), kj::str("{}"), nullptr), + tracing::Onset::WorkerInfo{}, kj::none); + }); + auto metricsForCatch = kj::addRef(incomingRequest->getMetrics()); auto metricsForProxyTask = kj::addRef(incomingRequest->getMetrics()); diff --git a/src/workerd/io/worker-interface.capnp b/src/workerd/io/worker-interface.capnp index 8a1588cb66a..fe3e2389866 100644 --- a/src/workerd/io/worker-interface.capnp +++ b/src/workerd/io/worker-interface.capnp @@ -557,6 +557,24 @@ interface JsRpcTarget $Cxx.allowCancellation { # Runs a Worker/DO's RPC method. } +interface TailStreamTarget $Cxx.allowCancellation { + # Interface used to deliver streaming tail events to a tail worker. + struct TailStreamParams { + events @0 :List(Trace.TailEvent); + } + + struct TailStreamResults { + pipeline @0 :TailStreamTarget; + # For an initial tailStream call, the pipeline would be expected to return + # a TailStreamTarget that would handle all the remaining events. Each of + # those subsequent calls to TailStreamTarget would not be expected to + # return a pipeline field at all. + } + + report @0 TailStreamParams -> TailStreamResults; + # Report one or more streaming tail events to a tail worker. +} + interface EventDispatcher @0xf20697475ec1752d { # Interface used to deliver events to a Worker's global event handlers. @@ -604,6 +622,13 @@ interface EventDispatcher @0xf20697475ec1752d { # # In C++, we use `WorkerInterface::customEvent()` to dispatch this event. + tailStreamSession @10 () -> (topLevel :TailStreamTarget) $Cxx.allowCancellation; + # Opens a streaming tail session. The call does not return until the session is complete. + # + # `topLevel` is the top-level tail session target, on which exactly one method call can + # be made. This call must be made using pipelining since `tailStreamSession()` won't return + # until after the call completes. + obsolete5 @5(); obsolete6 @6(); obsolete7 @7(); diff --git a/src/workerd/server/BUILD.bazel b/src/workerd/server/BUILD.bazel index e21335c6d94..58037da488b 100644 --- a/src/workerd/server/BUILD.bazel +++ b/src/workerd/server/BUILD.bazel @@ -122,6 +122,7 @@ wd_cc_library( "//src/workerd/api:rtti", "//src/workerd/api/node", "//src/workerd/io", + "//src/workerd/io:trace-stream", "//src/workerd/io:worker-entrypoint", "//src/workerd/jsg", "//src/workerd/util:perfetto", diff --git a/src/workerd/server/server.c++ b/src/workerd/server/server.c++ index 9be9dc570ec..559a9416094 100644 --- a/src/workerd/server/server.c++ +++ b/src/workerd/server/server.c++ @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include +#include namespace workerd::server { @@ -1464,9 +1466,187 @@ void Server::InspectorServiceIsolateRegistrar::registerIsolate( // ======================================================================================= namespace { + +// The TailStreamWriterState holds the current client-side state for a collection +// of streaming tail workers that a worker is reporting events to. +// TODO(later): It's possible that this class can be used for the internal implementation +// of streaming tail workers as well. If that is the ase, then will will likely be moved +// out to a separate file to allow reuse. For now tho, it's only used here so we'll keep +// it here. +struct TailStreamWriterState { + // The initial state of our tail worker writer is that it is pending the first + // onset event. During this time we will only have a collection of WorkerInterface + // instances. When our first event is reported (the onset) we will arrange to acquire + // tailStream capabilities from each then use those to report the initial onset. + using Pending = kj::Array>; + + struct Active { + // Reference to keep the worker interface instance alive. + kj::Maybe capability; + + // Every active tail worker target will have a queue. + bool pumping = false; + bool onsetSeen = false; + std::list queue; + }; + + struct Closed {}; + + kj::OneOf, Closed> inner; + kj::TaskSet& waitUntilTasks; + + TailStreamWriterState(Pending pending, kj::TaskSet& waitUntilTasks) + : inner(kj::mv(pending)), + waitUntilTasks(waitUntilTasks) {} + KJ_DISALLOW_COPY_AND_MOVE(TailStreamWriterState); + + void reportImpl(tracing::TailEvent&& event) { + // In reportImpl, our inner state must be active. + auto& actives = KJ_ASSERT_NONNULL(inner.tryGet>()); + + // We only care about sessions that are currently active. + kj::Vector alive(actives.size()); + for (auto& active: actives) { + if (active.capability != kj::none) { + alive.add(kj::mv(active)); + } + } + + if (alive.size() == 0) { + // Oh! We have no active sessions. Well, nevermind then, let's + // transition to a closed state and drop everything on the floor. + inner = Closed{}; + return; + } + + // Deliver the event to the queue and make sure we are processing. + for (Active& active: alive) { + active.queue.push_back(event.clone()); + if (!active.pumping) { + waitUntilTasks.add(pump(active)); + } + } + + inner = alive.releaseAsArray(); + } + + // Delivers the queued tail events to a streaming tail worker. + kj::Promise pump(Active& current) { + // At the start of the loop we should have an initial capability. + auto& cap = KJ_ASSERT_NONNULL(current.capability); + current.pumping = true; + KJ_DEFER(current.pumping = false); + + if (!current.onsetSeen) { + // Our first event... yay! Our first job here will be to dispatch + // the onset event to the tail worker. If the tail worker wishes + // to handle the remaining events in the strema, then it will return + // a new capability to which those would be reported. This is done + // via the "result.getPipeline()" API below. If hasPipeline() + // returns false then that means the tail worker did not return + // a handler for this stream and no further attempts to deliver + // events should be made for this stream. + current.onsetSeen = true; + KJ_ASSERT(!current.queue.empty()); + auto onsetEvent = kj::mv(current.queue.front()); + current.queue.pop_front(); + auto builder = cap.reportRequest(); + auto eventsBuilder = builder.initEvents(1); + onsetEvent.copyTo(eventsBuilder[0]); + auto result = co_await builder.send(); + if (!result.hasPipeline()) { + // If we don't have a pipeline result at this point, then the + // tail worker is not interested in events. Let's clear the + // capability and any events that may have been queued.. + current.capability = kj::none; + current.queue.clear(); + co_return; + } + // We have a pipeline! Let's replace our initial then proceed to + // deliver all the queued events (if any). + current.capability = result.getPipeline(); + + // Be sure to grab the new capability before we start delivering events. + cap = KJ_ASSERT_NONNULL(current.capability); + } + + // If we got this far then we have a handler for all of our events. + // Deliver streaming tail events in batches if possible. + while (!current.queue.empty()) { + auto builder = cap.reportRequest(); + auto eventsBuilder = builder.initEvents(current.queue.size()); + size_t n = 0; + for (auto& event: current.queue) { + event.copyTo(eventsBuilder[n++]); + } + current.queue.clear(); + co_await builder.send(); + } + } +}; + +// If we are using streaming tail workers, initialze the mechanism that will deliver events +// to that collection of tail workers. +kj::Maybe> initializeTailStreamWriter( + kj::Array> streamingTailWorkers, kj::TaskSet& waitUntilTasks) { + if (streamingTailWorkers.size() == 0) { + return kj::none; + } + return kj::heap( + // This lambda is called for every streaming tail event that is reported. We use + // the TailStreamWriterState for this strema to actually handle the event. + [state = kj::heap(kj::mv(streamingTailWorkers), waitUntilTasks)]( + IoContext& ioContext, tracing::TailEvent&& event) mutable { + KJ_SWITCH_ONEOF(state->inner) { + KJ_CASE_ONEOF(closed, TailStreamWriterState::Closed) { + // The tail stream has already been closed because we have received either + // an outcome or hibernate event. The writer should have failed and we + // actually shouldn't get here. Assert! + KJ_FAIL_ASSERT("tracing::TailStreamWriter report callback evoked after close"); + } + KJ_CASE_ONEOF(pending, TailStreamWriterState::Pending) { + // This is our first event! It has to be an onset event, which the writer + // should have validated for us. Assert if it is not an onset then proceed + // to start each of our tail working sessions. + KJ_ASSERT(event.event.is(), "First event must be an onset."); + + // Transitions into the active state by grabbing the pending client + // capability. + state->inner = KJ_MAP(wi, pending) { + auto customEvent = kj::heap(); + auto result = customEvent->getCap(); + ioContext.addTask( + wi->customEvent(kj::mv(customEvent)).attach(kj::mv(wi)).then([](auto&&) { + }, [](kj::Exception&&) {})); + return TailStreamWriterState::Active{ + .capability = kj::mv(result), + }; + }; + state->reportImpl(kj::mv(event)); + } + KJ_CASE_ONEOF(active, kj::Array) { + // Event cannot be a onset, which should have been validated by the writer. + KJ_ASSERT(!event.event.is(), "Only the first event can be an onset"); + auto final = event.event.is() || event.event.is(); + KJ_DEFER({ + if (final) state->inner = TailStreamWriterState::Closed{}; + }); + state->reportImpl(kj::mv(event)); + } + } + return !state->inner.is(); + }); +} + class RequestObserverWithTracer final: public RequestObserver, public WorkerInterface { public: - RequestObserverWithTracer(kj::Maybe> tracer): tracer(kj::mv(tracer)) {} + RequestObserverWithTracer(kj::Maybe> tracer, + kj::Array> streamingTailWorkers, + kj::TaskSet& waitUntilTasks) + : tracer(kj::mv(tracer)), + maybeTailStreamWriter( + initializeTailStreamWriter(kj::mv(streamingTailWorkers), waitUntilTasks)) {} + ~RequestObserverWithTracer() noexcept(false) { KJ_IF_SOME(t, tracer) { if (fetchStatus != 0) { @@ -1489,6 +1669,13 @@ class RequestObserverWithTracer final: public RequestObserver, public WorkerInte outcome = EventOutcome::EXCEPTION; } + void reportTailEvent( + IoContext& ioContext, kj::FunctionParam fn) override { + KJ_IF_SOME(writer, maybeTailStreamWriter) { + writer->report(ioContext, fn()); + } + } + // WorkerInterface kj::Promise request(kj::HttpMethod method, kj::StringPtr url, @@ -1574,6 +1761,7 @@ class RequestObserverWithTracer final: public RequestObserver, public WorkerInte private: kj::Maybe> tracer; kj::Maybe inner; + kj::Maybe> maybeTailStreamWriter; EventOutcome outcome = EventOutcome::OK; kj::uint fetchStatus = 0; }; @@ -1683,50 +1871,77 @@ class Server::WorkerService final: public Service, kj::Maybe> actor = kj::none) { TRACE_EVENT("workerd", "Server::WorkerService::startRequest()"); - // Setting up tail workers support. - auto tracer = kj::rc(); - auto executionModel = - actor == kj::none ? ExecutionModel::STATELESS : ExecutionModel::DURABLE_OBJECT; - auto workerTracer = - tracer->makeWorkerTracer(PipelineLogLevel::FULL, executionModel, kj::none /* scriptId */, - kj::none /* stableId */, kj::none /* scriptName */, kj::none /* scriptVersion */, - kj::none /* dispatchNamespace */, nullptr /* scriptTags */, kj::none /* entrypoint */); - auto& channels = KJ_ASSERT_NONNULL(ioChannels.tryGet()); - auto tailWorkers = KJ_MAP(service, channels.tails) -> kj::Own { - KJ_ASSERT(service != this, "A worker currently cannot log to itself"); - // Caution here... if the tail worker ends up have a cirular dependency - // on the worker we'll end up with an infinite loop trying to initialize. - // We can test this directly but it's more difficult to test indirect - // loops (dependency of dependency, etc). Here we're just going to keep - // it simple and just check the direct dependency. - return service->startRequest({}); - }; - - // When the tracer is complete, deliver the traces to both the parent - // and the tail workers. We do NOT want to attach the tracer to the - // tracer->onComplete() promise here because it is the destructor of - // the PipelineTracer that resolves the onComplete promise. If we attach - // the tracer to the promise the tracer won't be destroyed while the - // promise is still pending! Fortunately, the WorkerTracer we created - // will hold a strong reference to the worker tracer for as long as it - // is needed. As long as the WorkerTracer is still alive, the PipelineTracer - // will be. See below, we end up creating two references to the WorkerTracer, - // one held by the observer and one that will be passed to the IoContext. - // The PipelineTracer will be destroyed once both of those are freed. - waitUntilTasks.add(tracer->onComplete().then( - kj::coCapture([tailWorkers = kj::mv(tailWorkers)]( - kj::Array> traces) mutable -> kj::Promise { - for (auto& worker: tailWorkers) { - auto event = kj::heap( - workerd::api::TraceCustomEventImpl::TYPE, mapAddRef(traces)); - co_await worker->customEvent(kj::mv(event)).ignoreResult(); + kj::Array> legacyTailWorkers = nullptr; + kj::Array> streamingTailWorkers = nullptr; + // If streaming tail workers is enabled, then we will initialize two lists: + // one with services that only export the tail or trace handler (legacy tail + // workers) and one that exports the tailStream handler. We'll check tailStreams + // first. + if (util::Autogate::isEnabled(util::AutogateKey::STREAMING_TAIL_WORKERS)) { + kj::Vector> legacyList; + kj::Vector> streamingList; + for (auto& service: channels.tails) { + if (service->hasHandler("tailStream"_kj)) { + streamingList.add(service->startRequest({})); + } else if (service->hasHandler("tail") || service->hasHandler("trace")) { + legacyList.add(service->startRequest({})); + } } - co_return; - }))); + legacyTailWorkers = legacyList.releaseAsArray(); + streamingTailWorkers = streamingList.releaseAsArray(); + } else { + legacyTailWorkers = KJ_MAP(service, channels.tails) -> kj::Own { + KJ_ASSERT(service != this, "A worker currently cannot log to itself"); + // Caution here... if the tail worker ends up have a cirular dependency + // on the worker we'll end up with an infinite loop trying to initialize. + // We can test this directly but it's more difficult to test indirect + // loops (dependency of dependency, etc). Here we're just going to keep + // it simple and just check the direct dependency. + return service->startRequest({}); + }; + } + + kj::Maybe> workerTracer = kj::none; + kj::Own observer = kj::refcounted(); + + if (legacyTailWorkers.size() > 0) { + // Setting up legacy tail workers support, but only if we actually have tail workers + // configured. + auto tracer = kj::rc(); + auto executionModel = + actor == kj::none ? ExecutionModel::STATELESS : ExecutionModel::DURABLE_OBJECT; + workerTracer = tracer->makeWorkerTracer(PipelineLogLevel::FULL, executionModel, + kj::none /* scriptId */, kj::none /* stableId */, kj::none /* scriptName */, + kj::none /* scriptVersion */, kj::none /* dispatchNamespace */, nullptr /* scriptTags */, + kj::none /* entrypoint */); + + // When the tracer is complete, deliver the traces to both the parent + // and the legacy tail workers. We do NOT want to attach the tracer to the + // tracer->onComplete() promise here because it is the destructor of + // the PipelineTracer that resolves the onComplete promise. If we attach + // the tracer to the promise the tracer won't be destroyed while the + // promise is still pending! Fortunately, the WorkerTracer we created + // will hold a strong reference to the worker tracer for as long as it + // is needed. As long as the WorkerTracer is still alive, the PipelineTracer + // will be. See below, we end up creating two references to the WorkerTracer, + // one held by the observer and one that will be passed to the IoContext. + // The PipelineTracer will be destroyed once both of those are freed. + waitUntilTasks.add(tracer->onComplete().then( + kj::coCapture([tailWorkers = kj::mv(legacyTailWorkers)]( + kj::Array> traces) mutable -> kj::Promise { + for (auto& worker: tailWorkers) { + auto event = kj::heap( + workerd::api::TraceCustomEventImpl::TYPE, mapAddRef(traces)); + co_await worker->customEvent(kj::mv(event)).ignoreResult(); + } + co_return; + }))); + } - auto observer = kj::refcounted(kj::addRef(*workerTracer)); + observer = kj::refcounted( + mapAddRef(workerTracer), kj::mv(streamingTailWorkers), waitUntilTasks); return newWorkerEntrypoint(threadContext, kj::atomicAddRef(*worker), entrypointName, kj::mv(props), kj::mv(actor), kj::Own(this, kj::NullDisposer::instance), @@ -3543,6 +3758,18 @@ class Server::HttpListener final: public kj::Refcounted { return worker->customEvent(kj::mv(customEvent)).ignoreResult().attach(kj::mv(worker)); } + kj::Promise tailStreamSession(TailStreamSessionContext context) override { + auto customEvent = kj::heap(); + auto cap = customEvent->getCap(); + capnp::PipelineBuilder pipelineBuilder; + pipelineBuilder.setTopLevel(cap); + context.setPipeline(pipelineBuilder.build()); + context.getResults().setTopLevel(kj::mv(cap)); + + auto worker = getWorker(); + return worker->customEvent(kj::mv(customEvent)).ignoreResult().attach(kj::mv(worker)); + } + private: HttpListener& parent; kj::Maybe> worker; diff --git a/src/workerd/util/BUILD.bazel b/src/workerd/util/BUILD.bazel index cf5cee1c4a3..9d4edf94f2f 100644 --- a/src/workerd/util/BUILD.bazel +++ b/src/workerd/util/BUILD.bazel @@ -198,6 +198,13 @@ wd_cc_library( deps = ["@capnp-cpp//src/kj"], ) +wd_cc_library( + name = "completion-membrane", + hdrs = ["completion-membrane.h"], + visibility = ["//visibility:public"], + deps = ["@capnp-cpp//src/capnp"], +) + exports_files(["autogate.h"]) [ diff --git a/src/workerd/util/autogate.c++ b/src/workerd/util/autogate.c++ index 79376ebbf1b..c5264a9fa03 100644 --- a/src/workerd/util/autogate.c++ +++ b/src/workerd/util/autogate.c++ @@ -17,6 +17,8 @@ kj::StringPtr KJ_STRINGIFY(AutogateKey key) { switch (key) { case AutogateKey::TEST_WORKERD: return "test-workerd"_kj; + case AutogateKey::STREAMING_TAIL_WORKERS: + return "streaming-tail-workers"_kj; case AutogateKey::NumOfKeys: KJ_FAIL_ASSERT("NumOfKeys should not be used in getName"); } diff --git a/src/workerd/util/autogate.h b/src/workerd/util/autogate.h index e6e1cf97b46..f44f2193147 100644 --- a/src/workerd/util/autogate.h +++ b/src/workerd/util/autogate.h @@ -14,6 +14,7 @@ namespace workerd::util { // Workerd-specific list of autogate keys (can also be used in internal repo). enum class AutogateKey { TEST_WORKERD, + STREAMING_TAIL_WORKERS, NumOfKeys // Reserved for iteration. }; diff --git a/src/workerd/util/completion-membrane.h b/src/workerd/util/completion-membrane.h new file mode 100644 index 00000000000..fe63afcf1e8 --- /dev/null +++ b/src/workerd/util/completion-membrane.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +namespace workerd { + +// A membrane applied which detects when no capabilities are held any longer, at which point it +// fulfills a fulfiller. +// +// TODO(cleanup): This is generally useful, should it be part of capnp? +class CompletionMembrane final: public capnp::MembranePolicy, public kj::Refcounted { + public: + explicit CompletionMembrane(kj::Own> doneFulfiller) + : doneFulfiller(kj::mv(doneFulfiller)) {} + ~CompletionMembrane() noexcept(false) { + doneFulfiller->fulfill(); + } + + kj::Maybe inboundCall( + uint64_t interfaceId, uint16_t methodId, capnp::Capability::Client target) override { + return kj::none; + } + + kj::Maybe outboundCall( + uint64_t interfaceId, uint16_t methodId, capnp::Capability::Client target) override { + return kj::none; + } + + kj::Own addRef() override { + return kj::addRef(*this); + } + + private: + kj::Own> doneFulfiller; +}; + +// A membrane which revokes when some Promise is fulfilled. +// +// TODO(cleanup): This is generally useful, should it be part of capnp? +class RevokerMembrane final: public capnp::MembranePolicy, public kj::Refcounted { + public: + explicit RevokerMembrane(kj::Promise promise): promise(promise.fork()) {} + + kj::Maybe inboundCall( + uint64_t interfaceId, uint16_t methodId, capnp::Capability::Client target) override { + return kj::none; + } + + kj::Maybe outboundCall( + uint64_t interfaceId, uint16_t methodId, capnp::Capability::Client target) override { + return kj::none; + } + + kj::Own addRef() override { + return kj::addRef(*this); + } + + kj::Maybe> onRevoked() override { + return promise.addBranch(); + } + + private: + kj::ForkedPromise promise; +}; + +} // namespace workerd diff --git a/types/defines/trace.d.ts b/types/defines/trace.d.ts new file mode 100644 index 00000000000..ce16193855e --- /dev/null +++ b/types/defines/trace.d.ts @@ -0,0 +1,190 @@ +declare namespace TailStream { + +interface Header { + readonly name: string; + readonly value: string; +} + +interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; +} + +interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; +} + +interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; +} + +interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; +} + +interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; +} + +interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; +} + +interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; +} + +interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; +} +interface HibernatableWebSocketEventInfoError { + readonly type: "error"; +} +interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; +} + +interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: HibernatableWebSocketEventInfoClose | + HibernatableWebSocketEventInfoError | + HibernatableWebSocketEventInfoMessage; +} + +interface Resume { + readonly type: "resume"; + readonly attachment?: any; +} + +interface CustomEventInfo { + readonly type: "custom"; +} + +interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; +} + +type EventOutcome = "ok" | "canceled" | "exception" | "unknown" | "killSwitch" | + "daemonDown" | "exceededCpu" | "exceededMemory" | "loadShed" | + "responseStreamDisconnected" | "scriptNotFound"; + +interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; +} + +interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; +} + +interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: FetchEventInfo | JsRpcEventInfo | ScheduledEventInfo | + AlarmEventInfo | QueueEventInfo | EmailEventInfo | + TraceEventInfo | HibernatableWebSocketEventInfo | + Resume | CustomEventInfo; +} + +interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; +} + +interface Hibernate { + readonly type: "hibernate"; +} + +interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; +} + +interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; +} + +interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; +} + +interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; +} + +interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; +} + +interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; +} + +interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; +} + +interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; +} + +type Mark = DiagnosticChannelEvent | Exception | Log | Return | Link | Attribute[]; + +interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; +} + +type TailEventHandler = (event: TailEvent) => void | Promise; +type TailEventHandlerName = "onset" | "outcome" | "hibernate" | "spanOpen" | "spanClose" | + "diagnosticChannel" | "exception" | "log" | "return" | "link" | "attribute"; +type TailEventHandlerObject = Record; +type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; + +} diff --git a/types/generated-snapshot/2021-11-03/index.d.ts b/types/generated-snapshot/2021-11-03/index.d.ts index 904f2c38fd6..73446c0b010 100755 --- a/types/generated-snapshot/2021-11-03/index.d.ts +++ b/types/generated-snapshot/2021-11-03/index.d.ts @@ -409,6 +409,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -432,6 +437,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5386,6 +5392,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2021-11-03/index.ts b/types/generated-snapshot/2021-11-03/index.ts index 87941f4853c..e0db2c416f9 100755 --- a/types/generated-snapshot/2021-11-03/index.ts +++ b/types/generated-snapshot/2021-11-03/index.ts @@ -414,6 +414,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -437,6 +442,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5297,6 +5303,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-01-31/index.d.ts b/types/generated-snapshot/2022-01-31/index.d.ts index 897cbb47014..1d235325383 100755 --- a/types/generated-snapshot/2022-01-31/index.d.ts +++ b/types/generated-snapshot/2022-01-31/index.d.ts @@ -409,6 +409,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -432,6 +437,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5412,6 +5418,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-01-31/index.ts b/types/generated-snapshot/2022-01-31/index.ts index 1152546f550..c8e05019edd 100755 --- a/types/generated-snapshot/2022-01-31/index.ts +++ b/types/generated-snapshot/2022-01-31/index.ts @@ -414,6 +414,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -437,6 +442,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5323,6 +5329,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-03-21/index.d.ts b/types/generated-snapshot/2022-03-21/index.d.ts index 8eee7f84c18..716260882d2 100755 --- a/types/generated-snapshot/2022-03-21/index.d.ts +++ b/types/generated-snapshot/2022-03-21/index.d.ts @@ -412,6 +412,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -435,6 +440,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5437,6 +5443,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-03-21/index.ts b/types/generated-snapshot/2022-03-21/index.ts index 428110a9333..1173fc1fd9d 100755 --- a/types/generated-snapshot/2022-03-21/index.ts +++ b/types/generated-snapshot/2022-03-21/index.ts @@ -417,6 +417,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -440,6 +445,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5348,6 +5354,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-08-04/index.d.ts b/types/generated-snapshot/2022-08-04/index.d.ts index 02c84915179..6c436cbf7c7 100755 --- a/types/generated-snapshot/2022-08-04/index.d.ts +++ b/types/generated-snapshot/2022-08-04/index.d.ts @@ -412,6 +412,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -435,6 +440,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5438,6 +5444,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-08-04/index.ts b/types/generated-snapshot/2022-08-04/index.ts index b6e0f9fd93c..1650074ad49 100755 --- a/types/generated-snapshot/2022-08-04/index.ts +++ b/types/generated-snapshot/2022-08-04/index.ts @@ -417,6 +417,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -440,6 +445,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5349,6 +5355,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-10-31/index.d.ts b/types/generated-snapshot/2022-10-31/index.d.ts index 703b839a43d..76c16607577 100755 --- a/types/generated-snapshot/2022-10-31/index.d.ts +++ b/types/generated-snapshot/2022-10-31/index.d.ts @@ -412,6 +412,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -435,6 +440,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5441,6 +5447,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-10-31/index.ts b/types/generated-snapshot/2022-10-31/index.ts index e54a1a8b41e..7978ef32481 100755 --- a/types/generated-snapshot/2022-10-31/index.ts +++ b/types/generated-snapshot/2022-10-31/index.ts @@ -417,6 +417,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -440,6 +445,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5352,6 +5358,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-11-30/index.d.ts b/types/generated-snapshot/2022-11-30/index.d.ts index 62b6320347b..2ef04b83206 100755 --- a/types/generated-snapshot/2022-11-30/index.d.ts +++ b/types/generated-snapshot/2022-11-30/index.d.ts @@ -417,6 +417,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -440,6 +445,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5446,6 +5452,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2022-11-30/index.ts b/types/generated-snapshot/2022-11-30/index.ts index 022deac5f5b..1911aac7353 100755 --- a/types/generated-snapshot/2022-11-30/index.ts +++ b/types/generated-snapshot/2022-11-30/index.ts @@ -422,6 +422,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -445,6 +450,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5357,6 +5363,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2023-03-01/index.d.ts b/types/generated-snapshot/2023-03-01/index.d.ts index 46215ab1540..672cc7c8e2d 100755 --- a/types/generated-snapshot/2023-03-01/index.d.ts +++ b/types/generated-snapshot/2023-03-01/index.d.ts @@ -417,6 +417,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -440,6 +445,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5448,6 +5454,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2023-03-01/index.ts b/types/generated-snapshot/2023-03-01/index.ts index 780662329f8..f5761ef223f 100755 --- a/types/generated-snapshot/2023-03-01/index.ts +++ b/types/generated-snapshot/2023-03-01/index.ts @@ -422,6 +422,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -445,6 +450,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5359,6 +5365,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2023-07-01/index.d.ts b/types/generated-snapshot/2023-07-01/index.d.ts index c9a8a654416..aa84a7f72fe 100755 --- a/types/generated-snapshot/2023-07-01/index.d.ts +++ b/types/generated-snapshot/2023-07-01/index.d.ts @@ -417,6 +417,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -440,6 +445,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5448,6 +5454,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/2023-07-01/index.ts b/types/generated-snapshot/2023-07-01/index.ts index a1c3857b421..28ca9107c92 100755 --- a/types/generated-snapshot/2023-07-01/index.ts +++ b/types/generated-snapshot/2023-07-01/index.ts @@ -422,6 +422,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -445,6 +450,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5359,6 +5365,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/experimental/index.d.ts b/types/generated-snapshot/experimental/index.d.ts index 8079e18c9b8..a357db887d0 100755 --- a/types/generated-snapshot/experimental/index.d.ts +++ b/types/generated-snapshot/experimental/index.d.ts @@ -418,6 +418,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -441,6 +446,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5514,6 +5520,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/experimental/index.ts b/types/generated-snapshot/experimental/index.ts index dfd68bfaffb..3fa261f6b12 100755 --- a/types/generated-snapshot/experimental/index.ts +++ b/types/generated-snapshot/experimental/index.ts @@ -423,6 +423,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -446,6 +451,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5425,6 +5431,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/oldest/index.d.ts b/types/generated-snapshot/oldest/index.d.ts index ae271cb7319..dee1a367cf6 100755 --- a/types/generated-snapshot/oldest/index.d.ts +++ b/types/generated-snapshot/oldest/index.d.ts @@ -409,6 +409,11 @@ type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -432,6 +437,7 @@ interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5386,6 +5392,198 @@ declare module "cloudflare:sockets" { ): Socket; export { _connect as connect }; } +declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 diff --git a/types/generated-snapshot/oldest/index.ts b/types/generated-snapshot/oldest/index.ts index 860e6e5dd05..bb3ce38a238 100755 --- a/types/generated-snapshot/oldest/index.ts +++ b/types/generated-snapshot/oldest/index.ts @@ -414,6 +414,11 @@ export type ExportedHandlerTraceHandler = ( env: Env, ctx: ExecutionContext, ) => void | Promise; +export type ExportedHandlerTailStreamHandler = ( + event: TailStream.TailEvent, + env: Env, + ctx: ExecutionContext, +) => TailStream.TailEventHandlerType | Promise; export type ExportedHandlerScheduledHandler = ( controller: ScheduledController, env: Env, @@ -437,6 +442,7 @@ export interface ExportedHandler< fetch?: ExportedHandlerFetchHandler; tail?: ExportedHandlerTailHandler; trace?: ExportedHandlerTraceHandler; + tailStream?: ExportedHandlerTailStreamHandler; scheduled?: ExportedHandlerScheduledHandler; test?: ExportedHandlerTestHandler; email?: EmailExportedHandler; @@ -5297,6 +5303,198 @@ export declare namespace Rpc { >]: MethodOrProperty; }; } +export declare namespace TailStream { + interface Header { + readonly name: string; + readonly value: string; + } + interface FetchEventInfo { + readonly type: "fetch"; + readonly method: string; + readonly url: string; + readonly cfJson: string; + readonly headers: Header[]; + } + interface JsRpcEventInfo { + readonly type: "jsrpc"; + readonly methodName: string; + } + interface ScheduledEventInfo { + readonly type: "scheduled"; + readonly scheduledTime: Date; + readonly cron: string; + } + interface AlarmEventInfo { + readonly type: "alarm"; + readonly scheduledTime: Date; + } + interface QueueEventInfo { + readonly type: "queue"; + readonly queueName: string; + readonly batchSize: number; + } + interface EmailEventInfo { + readonly type: "email"; + readonly mailFrom: string; + readonly rcptTo: string; + readonly rawSize: number; + } + interface TraceEventInfo { + readonly type: "trace"; + readonly traces: (string | null)[]; + } + interface HibernatableWebSocketEventInfoMessage { + readonly type: "message"; + } + interface HibernatableWebSocketEventInfoError { + readonly type: "error"; + } + interface HibernatableWebSocketEventInfoClose { + readonly type: "close"; + readonly code: number; + readonly wasClean: boolean; + } + interface HibernatableWebSocketEventInfo { + readonly type: "hibernatableWebSocket"; + readonly info: + | HibernatableWebSocketEventInfoClose + | HibernatableWebSocketEventInfoError + | HibernatableWebSocketEventInfoMessage; + } + interface Resume { + readonly type: "resume"; + readonly attachment?: any; + } + interface CustomEventInfo { + readonly type: "custom"; + } + interface FetchResponseInfo { + readonly type: "fetch"; + readonly statusCode: number; + } + type EventOutcome = + | "ok" + | "canceled" + | "exception" + | "unknown" + | "killSwitch" + | "daemonDown" + | "exceededCpu" + | "exceededMemory" + | "loadShed" + | "responseStreamDisconnected" + | "scriptNotFound"; + interface ScriptVersion { + readonly id: string; + readonly tag?: string; + readonly message?: string; + } + interface Trigger { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Onset { + readonly type: "onset"; + readonly dispatchNamespace?: string; + readonly entrypoint?: string; + readonly scriptName?: string; + readonly scriptTags?: string[]; + readonly scriptVersion?: ScriptVersion; + readonly trigger?: Trigger; + readonly info: + | FetchEventInfo + | JsRpcEventInfo + | ScheduledEventInfo + | AlarmEventInfo + | QueueEventInfo + | EmailEventInfo + | TraceEventInfo + | HibernatableWebSocketEventInfo + | Resume + | CustomEventInfo; + } + interface Outcome { + readonly type: "outcome"; + readonly outcome: EventOutcome; + readonly cpuTime: number; + readonly wallTime: number; + } + interface Hibernate { + readonly type: "hibernate"; + } + interface SpanOpen { + readonly type: "spanOpen"; + readonly op?: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + } + interface SpanClose { + readonly type: "spanClose"; + readonly outcome: EventOutcome; + } + interface DiagnosticChannelEvent { + readonly type: "diagnosticChannel"; + readonly channel: string; + readonly message: any; + } + interface Exception { + readonly type: "exception"; + readonly name: string; + readonly message: string; + readonly stack?: string; + } + interface Log { + readonly type: "log"; + readonly level: "debug" | "error" | "info" | "log" | "warn"; + readonly message: string; + } + interface Return { + readonly type: "return"; + readonly info?: FetchResponseInfo | Attribute[]; + } + interface Link { + readonly type: "link"; + readonly label?: string; + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + } + interface Attribute { + readonly type: "attribute"; + readonly name: string; + readonly value: string | string[] | boolean | boolean[] | number | number[]; + } + type Mark = + | DiagnosticChannelEvent + | Exception + | Log + | Return + | Link + | Attribute[]; + interface TailEvent { + readonly traceId: string; + readonly invocationId: string; + readonly spanId: string; + readonly timestamp: Date; + readonly sequence: number; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + } + type TailEventHandler = (event: TailEvent) => void | Promise; + type TailEventHandlerName = + | "onset" + | "outcome" + | "hibernate" + | "spanOpen" + | "spanClose" + | "diagnosticChannel" + | "exception" + | "log" + | "return" + | "link" + | "attribute"; + type TailEventHandlerObject = Record; + type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; +} // Copyright (c) 2022-2023 Cloudflare, Inc. // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0