Skip to content
File

Blob: src/workerd/api/trace.h

cpp698 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#pragma once
6 
7/**
8 * Bindings for trace worker (ie. to support running wrangler tail).
9 */
10 
11#include <workerd/api/basics.h>
12#include <workerd/io/io-context.h>
13#include <workerd/io/trace.h>
14#include <workerd/jsg/jsg.h>
15 
16#include <kj/async.h>
17 
18namespace workerd::api {
19 
20class TraceItem;
21class TraceException;
22class TraceLog;
23class TraceDiagnosticChannelEvent;
24 
25class TailEvent final: public ExtendableEvent {
26 public:
27 explicit TailEvent(
28 jsg::Lock& js, kj::LiteralStringConst type, kj::ArrayPtr<kj::Own<Trace>> events);
29 
30 static jsg::Ref<TailEvent> constructor(kj::String type) = delete;
31 // TODO(soon): constructor?
32 
33 kj::Array<jsg::Ref<TraceItem>> getEvents();
34 
35 JSG_RESOURCE_TYPE(TailEvent) {
36 JSG_INHERIT(ExtendableEvent);
37 
38 JSG_LAZY_READONLY_INSTANCE_PROPERTY(events, getEvents);
39 // Deprecated. Please, use `events` instead.
40 JSG_LAZY_READONLY_INSTANCE_PROPERTY(traces, getEvents);
41 }
42 
43 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const;
44 
45 private:
46 kj::Array<jsg::Ref<TraceItem>> events;
47 
48 void visitForGc(jsg::GcVisitor& visitor) {
49 visitor.visitAll(events);
50 }
51};
52 
53struct ScriptVersion {
54 explicit ScriptVersion(workerd::ScriptVersion::Reader version);
55 ScriptVersion(const ScriptVersion&);
56 
57 jsg::Optional<kj::String> id;
58 jsg::Optional<kj::String> tag;
59 jsg::Optional<kj::String> message;
60 
61 JSG_STRUCT(id, tag, message);
62 
63 JSG_MEMORY_INFO(ScriptVersion) {
64 tracker.trackField("id", id);
65 tracker.trackField("tag", tag);
66 tracker.trackField("message", message);
67 }
68};
69 
70struct TracePreviewInfo {
71 explicit TracePreviewInfo(const tracing::TracePreview& preview);
72 TracePreviewInfo(const TracePreviewInfo&);
73 
74 kj::String id;
75 kj::String slug;
76 kj::String name;
77 
78 JSG_STRUCT(id, slug, name);
79 
80 JSG_MEMORY_INFO(TracePreviewInfo) {
81 tracker.trackField("id", id);
82 tracker.trackField("slug", slug);
83 tracker.trackField("name", name);
84 }
85};
86 
87class TraceItem final: public jsg::Object {
88 public:
89 using TailAttributeValue = kj::OneOf<bool, double, kj::String>;
90 
91 class FetchEventInfo;
92 class JsRpcEventInfo;
93 class ConnectEventInfo;
94 class ScheduledEventInfo;
95 class AlarmEventInfo;
96 class QueueEventInfo;
97 class EmailEventInfo;
98 class TailEventInfo;
99 class HibernatableWebSocketEventInfo;
100 class CustomEventInfo;
101 
102 explicit TraceItem(jsg::Lock& js, const Trace& trace);
103 
104 using EventInfo = kj::OneOf<jsg::Ref<FetchEventInfo>,
105 jsg::Ref<JsRpcEventInfo>,
106 jsg::Ref<ConnectEventInfo>,
107 jsg::Ref<ScheduledEventInfo>,
108 jsg::Ref<AlarmEventInfo>,
109 jsg::Ref<QueueEventInfo>,
110 jsg::Ref<EmailEventInfo>,
111 jsg::Ref<TailEventInfo>,
112 jsg::Ref<CustomEventInfo>,
113 jsg::Ref<HibernatableWebSocketEventInfo>>;
114 kj::Maybe<EventInfo> getEvent(jsg::Lock& js);
115 kj::Maybe<double> getEventTimestamp();
116 
117 kj::ArrayPtr<jsg::Ref<TraceLog>> getLogs();
118 kj::ArrayPtr<jsg::Ref<TraceException>> getExceptions();
119 kj::ArrayPtr<jsg::Ref<TraceDiagnosticChannelEvent>> getDiagnosticChannelEvents();
120 kj::Maybe<kj::StringPtr> getScriptName();
121 jsg::Optional<kj::StringPtr> getEntrypoint();
122 jsg::Optional<ScriptVersion> getScriptVersion();
123 jsg::Optional<kj::StringPtr> getDispatchNamespace();
124 jsg::Optional<kj::Array<kj::StringPtr>> getScriptTags();
125 jsg::Optional<TracePreviewInfo> getPreview();
126 jsg::Optional<jsg::Dict<TailAttributeValue>> getTailAttributes();
127 jsg::Optional<kj::StringPtr> getDurableObjectId();
128 kj::StringPtr getExecutionModel();
129 kj::StringPtr getOutcome();
130 
131 uint getCpuTime();
132 uint getWallTime();
133 bool getTruncated();
134 
135 JSG_RESOURCE_TYPE(TraceItem, CompatibilityFlags::Reader flags) {
136 JSG_LAZY_READONLY_INSTANCE_PROPERTY(event, getEvent);
137 JSG_LAZY_READONLY_INSTANCE_PROPERTY(eventTimestamp, getEventTimestamp);
138 JSG_LAZY_READONLY_INSTANCE_PROPERTY(logs, getLogs);
139 JSG_LAZY_READONLY_INSTANCE_PROPERTY(exceptions, getExceptions);
140 JSG_LAZY_READONLY_INSTANCE_PROPERTY(diagnosticsChannelEvents, getDiagnosticChannelEvents);
141 JSG_LAZY_READONLY_INSTANCE_PROPERTY(scriptName, getScriptName);
142 JSG_LAZY_READONLY_INSTANCE_PROPERTY(entrypoint, getEntrypoint);
143 JSG_LAZY_READONLY_INSTANCE_PROPERTY(scriptVersion, getScriptVersion);
144 JSG_LAZY_READONLY_INSTANCE_PROPERTY(dispatchNamespace, getDispatchNamespace);
145 JSG_LAZY_READONLY_INSTANCE_PROPERTY(scriptTags, getScriptTags);
146 JSG_LAZY_READONLY_INSTANCE_PROPERTY(tailAttributes, getTailAttributes);
147 JSG_LAZY_READONLY_INSTANCE_PROPERTY(preview, getPreview);
148 JSG_LAZY_READONLY_INSTANCE_PROPERTY(durableObjectId, getDurableObjectId);
149 JSG_LAZY_READONLY_INSTANCE_PROPERTY(outcome, getOutcome);
150 JSG_LAZY_READONLY_INSTANCE_PROPERTY(executionModel, getExecutionModel);
151 JSG_LAZY_READONLY_INSTANCE_PROPERTY(truncated, getTruncated);
152 JSG_LAZY_READONLY_INSTANCE_PROPERTY(cpuTime, getCpuTime);
153 JSG_LAZY_READONLY_INSTANCE_PROPERTY(wallTime, getWallTime);
154 }
155 
156 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const;
157 
158 private:
159 kj::Maybe<EventInfo> eventInfo;
160 kj::Maybe<double> eventTimestamp;
161 kj::Array<jsg::Ref<TraceLog>> logs;
162 kj::Array<jsg::Ref<TraceException>> exceptions;
163 kj::Array<jsg::Ref<TraceDiagnosticChannelEvent>> diagnosticChannelEvents;
164 kj::Maybe<kj::String> scriptName;
165 kj::Maybe<kj::String> entrypoint;
166 kj::Maybe<ScriptVersion> scriptVersion;
167 kj::Maybe<kj::String> dispatchNamespace;
168 jsg::Optional<kj::Array<kj::String>> scriptTags;
169 kj::Maybe<kj::Array<tracing::Attribute>> tailAttributes;
170 jsg::Optional<TracePreviewInfo> preview;
171 kj::Maybe<kj::String> durableObjectId;
172 kj::String executionModel;
173 kj::String outcome;
174 uint cpuTime;
175 uint wallTime;
176 bool truncated;
177};
178 
179// When adding a new TraceItem eventInfo type, it is important not to
180// try keeping a reference to the Trace and tracing::*EventInfo inputs.
181// They are kj heap objects that have a lifespan that is managed independently
182// of the TraceItem object. Each of the implementations here extract the
183// necessary detail on creation and use LAZY instance properties to minimize
184// copying and allocation necessary when accessing these values.
185// TODO(cleanup): Later we can further optimize by creating the JS objects
186// immediately on creation.
187 
188// While this class is named FetchEventInfo, it encapsulates both the actual
189// FetchEventInfo as well as the FetchResponseInfo, which is an (optional)
190// sibling field (see worker.capnp). The internal FetchEventInfo (and
191// EventInfo in general) only represents the original event, not any
192// subsequent results such as the HTTP response. Internally, FetchEventInfo is
193// populated as soon as a request comes in, whereas the FetchResponseInfo is
194// only set once the request has finished entirely (along with the outcome,
195// see TraceItem::getOutcome).
196class TraceItem::FetchEventInfo final: public jsg::Object {
197 public:
198 class Request;
199 class Response;
200 
201 explicit FetchEventInfo(jsg::Lock& js,
202 const Trace& trace,
203 const tracing::FetchEventInfo& eventInfo,
204 kj::Maybe<const tracing::FetchResponseInfo&> responseInfo);
205 
206 jsg::Ref<Request> getRequest();
207 jsg::Optional<jsg::Ref<Response>> getResponse();
208 
209 // TODO(cleanup) Use struct types more?
210 JSG_RESOURCE_TYPE(FetchEventInfo) {
211 JSG_LAZY_READONLY_INSTANCE_PROPERTY(response, getResponse);
212 JSG_LAZY_READONLY_INSTANCE_PROPERTY(request, getRequest);
213 }
214 
215 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const;
216 
217 private:
218 jsg::Ref<Request> request;
219 jsg::Optional<jsg::Ref<Response>> response;
220};
221 
222class TraceItem::FetchEventInfo::Request final: public jsg::Object {
223 public:
224 struct Detail: public kj::Refcounted {
225 jsg::Optional<jsg::V8Ref<v8::Object>> cf;
226 kj::Array<tracing::FetchEventInfo::Header> headers;
227 kj::String method;
228 kj::String url;
229 
230 Detail(jsg::Optional<jsg::V8Ref<v8::Object>> cf,
231 kj::Array<tracing::FetchEventInfo::Header> headers,
232 kj::String method,
233 kj::String url);
234 
235 JSG_MEMORY_INFO(Detail) {
236 tracker.trackField("cf", cf);
237 for (const auto& header: headers) {
238 tracker.trackField(nullptr, header);
239 }
240 tracker.trackField("method", method);
241 tracker.trackField("url", url);
242 }
243 };
244 
245 explicit Request(jsg::Lock& js, const Trace& trace, const tracing::FetchEventInfo& eventInfo);
246 
247 // Creates a possibly unredacted instance that shared a ref of the Detail
248 explicit Request(Detail& detail, bool redacted = true);
249 
250 jsg::Optional<jsg::V8Ref<v8::Object>> getCf(jsg::Lock& js);
251 jsg::Dict<kj::String, kj::String> getHeaders(jsg::Lock& js);
252 kj::StringPtr getMethod();
253 kj::String getUrl();
254 
255 jsg::Ref<Request> getUnredacted(jsg::Lock& js);
256 
257 JSG_RESOURCE_TYPE(Request) {
258 JSG_LAZY_READONLY_INSTANCE_PROPERTY(cf, getCf);
259 JSG_LAZY_READONLY_INSTANCE_PROPERTY(headers, getHeaders);
260 JSG_LAZY_READONLY_INSTANCE_PROPERTY(method, getMethod);
261 JSG_LAZY_READONLY_INSTANCE_PROPERTY(url, getUrl);
262 
263 JSG_METHOD(getUnredacted);
264 }
265 
266 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
267 tracker.trackField("detail", detail);
268 }
269 
270 private:
271 bool redacted = true;
272 kj::Own<Detail> detail;
273};
274 
275class TraceItem::FetchEventInfo::Response final: public jsg::Object {
276 public:
277 explicit Response(const Trace& trace, const tracing::FetchResponseInfo& responseInfo);
278 
279 uint16_t getStatus();
280 
281 JSG_RESOURCE_TYPE(Response) {
282 JSG_LAZY_READONLY_INSTANCE_PROPERTY(status, getStatus);
283 }
284 
285 private:
286 uint16_t status;
287};
288 
289class TraceItem::JsRpcEventInfo final: public jsg::Object {
290 public:
291 explicit JsRpcEventInfo(const Trace& trace, const tracing::JsRpcEventInfo& eventInfo);
292 
293 // We call this `rpcMethod` to make clear this is an RPC event, since some tail workers rely
294 // on duck-typing EventInfo based on the properties present. (`methodName` might be ambiguous
295 // since HTTP also has methods.)
296 //
297 // TODO(someday): Clearly there should be a better way to distinguish event types?
298 kj::StringPtr getRpcMethod();
299 
300 JSG_RESOURCE_TYPE(JsRpcEventInfo) {
301 JSG_LAZY_READONLY_INSTANCE_PROPERTY(rpcMethod, getRpcMethod);
302 }
303 
304 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
305 tracker.trackField("rpcMethod", rpcMethod);
306 }
307 
308 private:
309 kj::String rpcMethod;
310};
311 
312class TraceItem::ConnectEventInfo final: public jsg::Object {
313 public:
314 explicit ConnectEventInfo(
315 jsg::Lock& js, const Trace& trace, const tracing::ConnectEventInfo& eventInfo);
316 
317 JSG_RESOURCE_TYPE(ConnectEventInfo) {}
318};
319 
320class TraceItem::ScheduledEventInfo final: public jsg::Object {
321 public:
322 explicit ScheduledEventInfo(const Trace& trace, const tracing::ScheduledEventInfo& eventInfo);
323 
324 double getScheduledTime();
325 kj::StringPtr getCron();
326 
327 JSG_RESOURCE_TYPE(ScheduledEventInfo) {
328 JSG_LAZY_READONLY_INSTANCE_PROPERTY(scheduledTime, getScheduledTime);
329 JSG_LAZY_READONLY_INSTANCE_PROPERTY(cron, getCron);
330 }
331 
332 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
333 tracker.trackField("cron", cron);
334 }
335 
336 private:
337 double scheduledTime;
338 kj::String cron;
339};
340 
341class TraceItem::AlarmEventInfo final: public jsg::Object {
342 public:
343 explicit AlarmEventInfo(const Trace& trace, const tracing::AlarmEventInfo& eventInfo);
344 
345 kj::Date getScheduledTime();
346 
347 JSG_RESOURCE_TYPE(AlarmEventInfo) {
348 JSG_LAZY_READONLY_INSTANCE_PROPERTY(scheduledTime, getScheduledTime);
349 }
350 
351 private:
352 kj::Date scheduledTime;
353};
354 
355class TraceItem::QueueEventInfo final: public jsg::Object {
356 public:
357 explicit QueueEventInfo(const Trace& trace, const tracing::QueueEventInfo& eventInfo);
358 
359 kj::StringPtr getQueueName();
360 uint32_t getBatchSize();
361 // TODO(now): Add something about the timestamp(s) of the newest/oldest message(s) in the batch?
362 
363 JSG_RESOURCE_TYPE(QueueEventInfo) {
364 JSG_LAZY_READONLY_INSTANCE_PROPERTY(queue, getQueueName);
365 JSG_LAZY_READONLY_INSTANCE_PROPERTY(batchSize, getBatchSize);
366 }
367 
368 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
369 tracker.trackField("queueName", queueName);
370 }
371 
372 private:
373 kj::String queueName;
374 uint32_t batchSize;
375};
376 
377class TraceItem::EmailEventInfo final: public jsg::Object {
378 public:
379 explicit EmailEventInfo(const Trace& trace, const tracing::EmailEventInfo& eventInfo);
380 
381 kj::StringPtr getMailFrom();
382 kj::StringPtr getRcptTo();
383 uint32_t getRawSize();
384 
385 JSG_RESOURCE_TYPE(EmailEventInfo) {
386 JSG_LAZY_READONLY_INSTANCE_PROPERTY(mailFrom, getMailFrom);
387 JSG_LAZY_READONLY_INSTANCE_PROPERTY(rcptTo, getRcptTo);
388 JSG_LAZY_READONLY_INSTANCE_PROPERTY(rawSize, getRawSize);
389 }
390 
391 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
392 tracker.trackField("mailFrom", mailFrom);
393 tracker.trackField("rcptTo", rcptTo);
394 }
395 
396 private:
397 kj::String mailFrom;
398 kj::String rcptTo;
399 uint32_t rawSize;
400};
401 
402class TraceItem::TailEventInfo final: public jsg::Object {
403 public:
404 class TailItem;
405 
406 explicit TailEventInfo(
407 jsg::Lock& js, const Trace& trace, const tracing::TraceEventInfo& eventInfo);
408 
409 kj::Array<jsg::Ref<TailItem>> getConsumedEvents();
410 
411 JSG_RESOURCE_TYPE(TailEventInfo) {
412 JSG_LAZY_READONLY_INSTANCE_PROPERTY(consumedEvents, getConsumedEvents);
413 }
414 
415 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const;
416 
417 private:
418 kj::Array<jsg::Ref<TailItem>> consumedEvents;
419};
420 
421class TraceItem::TailEventInfo::TailItem final: public jsg::Object {
422 public:
423 explicit TailItem(const tracing::TraceEventInfo::TraceItem& traceItem);
424 
425 kj::Maybe<kj::StringPtr> getScriptName();
426 
427 JSG_RESOURCE_TYPE(TailItem) {
428 JSG_LAZY_READONLY_INSTANCE_PROPERTY(scriptName, getScriptName);
429 }
430 
431 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
432 tracker.trackField("scriptName", scriptName);
433 }
434 
435 private:
436 kj::Maybe<kj::String> scriptName;
437};
438 
439class TraceItem::HibernatableWebSocketEventInfo final: public jsg::Object {
440 public:
441 class Message;
442 class Close;
443 class Error;
444 
445 explicit HibernatableWebSocketEventInfo(jsg::Lock& js,
446 const Trace& trace,
447 tracing::HibernatableWebSocketEventInfo::Message eventInfo);
448 explicit HibernatableWebSocketEventInfo(
449 jsg::Lock& js, const Trace& trace, tracing::HibernatableWebSocketEventInfo::Close eventInfo);
450 explicit HibernatableWebSocketEventInfo(
451 jsg::Lock& js, const Trace& trace, tracing::HibernatableWebSocketEventInfo::Error eventInfo);
452 
453 using Type = kj::OneOf<jsg::Ref<Message>, jsg::Ref<Close>, jsg::Ref<Error>>;
454 
455 Type getEvent();
456 
457 JSG_RESOURCE_TYPE(HibernatableWebSocketEventInfo) {
458 JSG_READONLY_INSTANCE_PROPERTY(getWebSocketEvent, getEvent);
459 }
460 
461 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const;
462 
463 private:
464 Type eventType;
465};
466 
467class TraceItem::HibernatableWebSocketEventInfo::Message final: public jsg::Object {
468 public:
469 explicit Message(const Trace& trace, tracing::HibernatableWebSocketEventInfo::Message eventInfo)
470 : eventInfo(eventInfo) {}
471 
472 static constexpr kj::StringPtr webSocketEventType = "message"_kj;
473 kj::StringPtr getWebSocketEventType() {
474 return webSocketEventType;
475 }
476 
477 JSG_RESOURCE_TYPE(Message) {
478 JSG_READONLY_INSTANCE_PROPERTY(webSocketEventType, getWebSocketEventType);
479 }
480 
481 private:
482 const tracing::HibernatableWebSocketEventInfo::Message eventInfo;
483};
484 
485class TraceItem::HibernatableWebSocketEventInfo::Close final: public jsg::Object {
486 public:
487 explicit Close(const Trace& trace, tracing::HibernatableWebSocketEventInfo::Close eventInfo)
488 : eventInfo(eventInfo) {}
489 
490 static constexpr kj::StringPtr webSocketEventType = "close"_kj;
491 kj::StringPtr getWebSocketEventType() {
492 return webSocketEventType;
493 }
494 
495 uint16_t getCode();
496 bool getWasClean();
497 
498 JSG_RESOURCE_TYPE(Close) {
499 JSG_READONLY_INSTANCE_PROPERTY(webSocketEventType, getWebSocketEventType);
500 JSG_READONLY_INSTANCE_PROPERTY(code, getCode);
501 JSG_READONLY_INSTANCE_PROPERTY(wasClean, getWasClean);
502 }
503 
504 private:
505 const tracing::HibernatableWebSocketEventInfo::Close eventInfo;
506};
507 
508class TraceItem::HibernatableWebSocketEventInfo::Error final: public jsg::Object {
509 public:
510 explicit Error(const Trace& trace, tracing::HibernatableWebSocketEventInfo::Error eventInfo)
511 : eventInfo(eventInfo) {}
512 
513 static constexpr kj::StringPtr webSocketEventType = "error"_kj;
514 kj::StringPtr getWebSocketEventType() {
515 return webSocketEventType;
516 }
517 
518 JSG_RESOURCE_TYPE(Error) {
519 JSG_READONLY_INSTANCE_PROPERTY(webSocketEventType, getWebSocketEventType);
520 }
521 
522 private:
523 const tracing::HibernatableWebSocketEventInfo::Error eventInfo;
524};
525 
526class TraceItem::CustomEventInfo final: public jsg::Object {
527 public:
528 explicit CustomEventInfo(const Trace& trace, const tracing::CustomEventInfo& eventInfo);
529 
530 JSG_RESOURCE_TYPE(CustomEventInfo) {}
531 
532 private:
533 const tracing::CustomEventInfo& eventInfo;
534};
535 
536class TraceDiagnosticChannelEvent final: public jsg::Object {
537 public:
538 explicit TraceDiagnosticChannelEvent(
539 const Trace& trace, const tracing::DiagnosticChannelEvent& eventInfo);
540 
541 double getTimestamp();
542 kj::StringPtr getChannel();
543 jsg::JsValue getMessage(jsg::Lock& js);
544 
545 JSG_RESOURCE_TYPE(TraceDiagnosticChannelEvent) {
546 JSG_LAZY_READONLY_INSTANCE_PROPERTY(timestamp, getTimestamp);
547 JSG_LAZY_READONLY_INSTANCE_PROPERTY(channel, getChannel);
548 JSG_LAZY_READONLY_INSTANCE_PROPERTY(message, getMessage);
549 }
550 
551 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
552 tracker.trackField("channel", channel);
553 tracker.trackFieldWithSize("message", message.size());
554 }
555 
556 private:
557 double timestamp;
558 kj::String channel;
559 kj::Array<kj::byte> message;
560};
561 
562class TraceLog final: public jsg::Object {
563 public:
564 TraceLog(jsg::Lock& js, const Trace& trace, const tracing::Log& log);
565 
566 double getTimestamp();
567 kj::StringPtr getLevel();
568 jsg::V8Ref<v8::Object> getMessage(jsg::Lock& js);
569 
570 JSG_RESOURCE_TYPE(TraceLog) {
571 JSG_LAZY_READONLY_INSTANCE_PROPERTY(timestamp, getTimestamp);
572 JSG_LAZY_READONLY_INSTANCE_PROPERTY(level, getLevel);
573 JSG_LAZY_READONLY_INSTANCE_PROPERTY(message, getMessage);
574 }
575 
576 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
577 tracker.trackField("message", message);
578 }
579 
580 private:
581 double timestamp;
582 kj::LiteralStringConst level;
583 jsg::V8Ref<v8::Object> message;
584};
585 
586class TraceException final: public jsg::Object {
587 public:
588 TraceException(const Trace& trace, const tracing::Exception& exception);
589 
590 double getTimestamp();
591 kj::StringPtr getName();
592 kj::StringPtr getMessage();
593 jsg::Optional<kj::StringPtr> getStack(jsg::Lock& js);
594 
595 JSG_RESOURCE_TYPE(TraceException) {
596 JSG_LAZY_READONLY_INSTANCE_PROPERTY(timestamp, getTimestamp);
597 JSG_LAZY_READONLY_INSTANCE_PROPERTY(message, getMessage);
598 JSG_LAZY_READONLY_INSTANCE_PROPERTY(name, getName);
599 JSG_LAZY_READONLY_INSTANCE_PROPERTY(stack, getStack);
600 }
601 
602 void visitForMemoryInfo(jsg::MemoryTracker& tracker) const {
603 tracker.trackField("name", name);
604 tracker.trackField("message", message);
605 }
606 
607 private:
608 double timestamp;
609 kj::String name;
610 kj::String message;
611 kj::Maybe<kj::String> stack;
612};
613 
614class TraceMetrics final: public jsg::Object {
615 public:
616 explicit TraceMetrics(uint cpuTime, uint wallTime);
617 
618 uint getCPUTime() {
619 return cpuTime;
620 };
621 uint getWallTime() {
622 return wallTime;
623 };
624 
625 JSG_RESOURCE_TYPE(TraceMetrics) {
626 JSG_READONLY_INSTANCE_PROPERTY(cpuTime, getCPUTime);
627 JSG_READONLY_INSTANCE_PROPERTY(wallTime, getWallTime);
628 
629 JSG_TS_ROOT();
630 }
631 
632 private:
633 uint cpuTime;
634 uint wallTime;
635};
636 
637class UnsafeTraceMetrics final: public jsg::Object {
638 public:
639 jsg::Ref<TraceMetrics> fromTrace(jsg::Lock& js, jsg::Ref<TraceItem> item);
640 
641 JSG_RESOURCE_TYPE(UnsafeTraceMetrics) {
642 JSG_METHOD(fromTrace);
643 
644 JSG_TS_ROOT();
645 }
646};
647 
648class TraceCustomEvent final: public WorkerInterface::CustomEvent {
649 public:
650 TraceCustomEvent(uint16_t typeId, kj::Array<kj::Own<Trace>> traces)
651 : typeId(typeId),
652 traces(kj::mv(traces)) {}
653 
654 kj::Promise<Result> run(kj::Own<IoContext::IncomingRequest> incomingRequest,
655 kj::Maybe<kj::StringPtr> entrypointName,
656 kj::Maybe<Worker::VersionInfo> versionInfo,
657 Frankenvalue props,
658 kj::TaskSet& waitUntilTasks,
659 bool isDynamicDispatch) override;
660 
661 kj::Promise<Result> sendRpc(capnp::HttpOverCapnpFactory& httpOverCapnpFactory,
662 capnp::ByteStreamFactory& byteStreamFactory,
663 rpc::EventDispatcher::Client dispatcher) override;
664 
665 uint16_t getType() override {
666 return typeId;
667 }
668 
669 tracing::EventInfo getEventInfo() const override;
670 
671 kj::Promise<Result> notSupported() override {
672 KJ_UNIMPLEMENTED("trace event not supported");
673 }
674 
675 static constexpr uint16_t TYPE = 2;
676 
677 private:
678 uint16_t typeId;
679 kj::Array<kj::Own<workerd::Trace>> traces;
680};
681 
682#define EW_TRACE_ISOLATE_TYPES \
683 api::TracePreviewInfo, api::ScriptVersion, api::TailEvent, api::TraceItem, \
684 api::TraceItem::AlarmEventInfo, api::TraceItem::ConnectEventInfo, \
685 api::TraceItem::CustomEventInfo, api::TraceItem::ScheduledEventInfo, \
686 api::TraceItem::QueueEventInfo, api::TraceItem::EmailEventInfo, \
687 api::TraceItem::TailEventInfo, api::TraceItem::TailEventInfo::TailItem, \
688 api::TraceItem::FetchEventInfo, api::TraceItem::FetchEventInfo::Request, \
689 api::TraceItem::FetchEventInfo::Response, api::TraceItem::JsRpcEventInfo, \
690 api::TraceItem::HibernatableWebSocketEventInfo, \
691 api::TraceItem::HibernatableWebSocketEventInfo::Message, \
692 api::TraceItem::HibernatableWebSocketEventInfo::Close, \
693 api::TraceItem::HibernatableWebSocketEventInfo::Error, api::TraceLog, api::TraceException, \
694 api::TraceDiagnosticChannelEvent, api::TraceMetrics, api::UnsafeTraceMetrics
695// The list of trace.h types that are added to worker.c++'s JSG_DECLARE_ISOLATE_TYPE
696 
697} // namespace workerd::api