diff --git a/src/workerd/io/io-context.c++ b/src/workerd/io/io-context.c++ index be11c142a161..09c3439926b1 100644 --- a/src/workerd/io/io-context.c++ +++ b/src/workerd/io/io-context.c++ @@ -202,7 +202,7 @@ IoContext::IncomingRequest::IoContext_IncomingRequest(kj::Own context kj::Own ioChannelFactoryParam, kj::Own metricsParam, kj::Maybe> workerTracer, - kj::Rc invocationSpanContext) + tracing::InvocationSpanContext invocationSpanContext) : context(kj::mv(contextParam)), metrics(kj::mv(metricsParam)), workerTracer(kj::mv(workerTracer)), diff --git a/src/workerd/io/io-context.h b/src/workerd/io/io-context.h index d78d712419ba..2bf23326817f 100644 --- a/src/workerd/io/io-context.h +++ b/src/workerd/io/io-context.h @@ -111,7 +111,7 @@ class IoContext_IncomingRequest final { kj::Own ioChannelFactory, kj::Own metrics, kj::Maybe> workerTracer, - kj::Rc invocationSpanContext); + tracing::InvocationSpanContext invocationSpanContext); KJ_DISALLOW_COPY_AND_MOVE(IoContext_IncomingRequest); ~IoContext_IncomingRequest() noexcept(false); @@ -163,7 +163,7 @@ class IoContext_IncomingRequest final { // The invocation span context is a unique identifier for a specific // worker invocation. - kj::Rc& getInvocationSpanContext() { + tracing::InvocationSpanContext& getInvocationSpanContext() { return invocationSpanContext; } @@ -176,7 +176,7 @@ class IoContext_IncomingRequest final { // The invocation span context identifies the trace id, invocation id, and root // span for the current request. Every invocation of a worker function always // has a root span, even if it is not explicitly traced. - kj::Rc invocationSpanContext; + tracing::InvocationSpanContext invocationSpanContext; bool wasDelivered = false; diff --git a/src/workerd/io/trace-test.c++ b/src/workerd/io/trace-test.c++ index 87fd638ad227..98147246485d 100644 --- a/src/workerd/io/trace-test.c++ +++ b/src/workerd/io/trace-test.c++ @@ -91,46 +91,46 @@ KJ_TEST("InvocationSpanContext") { // We can create an InvocationSpanContext... static constexpr auto kCheck = TraceId(0x2a2a2a2a2a2a2a2a, 0x2a2a2a2a2a2a2a2a); - KJ_EXPECT(sc->getTraceId() == kCheck); - KJ_EXPECT(sc->getInvocationId() == kCheck); - KJ_EXPECT(sc->getSpanId() == SpanId(1)); + KJ_EXPECT(sc.getTraceId() == kCheck); + KJ_EXPECT(sc.getInvocationId() == kCheck); + KJ_EXPECT(sc.getSpanId() == SpanId(1)); // And serialize that to a capnp struct... capnp::MallocMessageBuilder builder; auto root = builder.initRoot(); - sc->toCapnp(root); + sc.toCapnp(root); // Then back again... auto sc2 = KJ_ASSERT_NONNULL(InvocationSpanContext::fromCapnp(root.asReader())); - KJ_EXPECT(sc2->getTraceId() == kCheck); - KJ_EXPECT(sc2->getInvocationId() == kCheck); - KJ_EXPECT(sc2->getSpanId() == SpanId(1)); - KJ_EXPECT(sc2->isTrigger()); + KJ_EXPECT(sc2.getTraceId() == kCheck); + KJ_EXPECT(sc2.getInvocationId() == kCheck); + KJ_EXPECT(sc2.getSpanId() == SpanId(1)); + KJ_EXPECT(sc2.isTrigger()); // The one that has been deserialized from capnp cannot create children... try { - sc2->newChild(); + sc2.newChild(); KJ_FAIL_ASSERT("should not be able to create child span with SpanContext from capnp"); } catch (kj::Exception& ex) { KJ_EXPECT(ex.getDescription() == "expected !isTrigger(); unable to create child spans on this context"_kj); } - auto sc3 = sc->newChild(); - KJ_EXPECT(sc3->getTraceId() == kCheck); - KJ_EXPECT(sc3->getInvocationId() == kCheck); - KJ_EXPECT(sc3->getSpanId() == SpanId(2)); + auto sc3 = sc.newChild(); + KJ_EXPECT(sc3.getTraceId() == kCheck); + KJ_EXPECT(sc3.getInvocationId() == kCheck); + KJ_EXPECT(sc3.getSpanId() == SpanId(2)); auto sc4 = InvocationSpanContext::newForInvocation(sc2, fakeEntropySource); - KJ_EXPECT(sc4->getTraceId() == kCheck); - KJ_EXPECT(sc4->getInvocationId() == kCheck); - KJ_EXPECT(sc4->getSpanId() == SpanId(3)); - - auto& sc5 = KJ_ASSERT_NONNULL(sc4->getParent()); - KJ_EXPECT(sc5->getTraceId() == kCheck); - KJ_EXPECT(sc5->getInvocationId() == kCheck); - KJ_EXPECT(sc5->getSpanId() == SpanId(1)); - KJ_EXPECT(sc5->isTrigger()); + KJ_EXPECT(sc4.getTraceId() == kCheck); + KJ_EXPECT(sc4.getInvocationId() == kCheck); + KJ_EXPECT(sc4.getSpanId() == SpanId(3)); + + auto& sc5 = KJ_ASSERT_NONNULL(sc4.getParent()); + KJ_EXPECT(sc5.getTraceId() == kCheck); + KJ_EXPECT(sc5.getInvocationId() == kCheck); + KJ_EXPECT(sc5.getSpanId() == SpanId(1)); + KJ_EXPECT(sc5.isTrigger()); } KJ_TEST("Read/Write FetchEventInfo works") { @@ -532,9 +532,9 @@ KJ_TEST("Read/Write TraceEvent works") { tracing::TailEvent info2(reader); KJ_ASSERT(info2.timestamp == kj::UNIX_EPOCH); KJ_ASSERT(info2.sequence == 0); - KJ_ASSERT(info2.context.invocationId == context->getInvocationId()); - KJ_ASSERT(info2.context.traceId == context->getTraceId()); - KJ_ASSERT(info2.context.spanId == context->getSpanId()); + KJ_ASSERT(info2.context.invocationId == context.getInvocationId()); + KJ_ASSERT(info2.context.traceId == context.getTraceId()); + KJ_ASSERT(info2.context.spanId == context.getSpanId()); auto& event = KJ_ASSERT_NONNULL(info2.event.tryGet()); auto& log2 = KJ_ASSERT_NONNULL(event.tryGet()); @@ -545,9 +545,9 @@ KJ_TEST("Read/Write TraceEvent works") { tracing::TailEvent info3 = info.clone(); KJ_ASSERT(info3.timestamp == kj::UNIX_EPOCH); KJ_ASSERT(info3.sequence == 0); - KJ_ASSERT(info3.context.invocationId == context->getInvocationId()); - KJ_ASSERT(info3.context.traceId == context->getTraceId()); - KJ_ASSERT(info3.context.spanId == context->getSpanId()); + KJ_ASSERT(info3.context.invocationId == context.getInvocationId()); + KJ_ASSERT(info3.context.traceId == context.getTraceId()); + KJ_ASSERT(info3.context.spanId == context.getSpanId()); auto& event2 = KJ_ASSERT_NONNULL(info3.event.tryGet()); auto& log3 = KJ_ASSERT_NONNULL(event2.tryGet()); diff --git a/src/workerd/io/trace.c++ b/src/workerd/io/trace.c++ index e4a982af0254..5ae3deb9e10e 100644 --- a/src/workerd/io/trace.c++ +++ b/src/workerd/io/trace.c++ @@ -127,7 +127,7 @@ kj::String TraceId::toW3C() const { } namespace { -uint64_t getRandom64Bit(kj::Maybe& entropySource) { +uint64_t getRandom64Bit(const kj::Maybe& entropySource) { uint64_t ret = 0; uint8_t tries = 0; @@ -178,31 +178,34 @@ InvocationSpanContext::InvocationSpanContext(kj::Badge, TraceId traceId, TraceId invocationId, SpanId spanId, - kj::Maybe> parentSpanContext) + kj::Maybe parentSpanContext) : entropySource(entropySource), traceId(kj::mv(traceId)), invocationId(kj::mv(invocationId)), spanId(kj::mv(spanId)), - parentSpanContext(kj::mv(parentSpanContext)) {} + parentSpanContext(parentSpanContext.map([](const InvocationSpanContext& ctx) { + return kj::heap(ctx.clone()); + })) {} -kj::Rc InvocationSpanContext::newChild() { +InvocationSpanContext InvocationSpanContext::newChild() const { KJ_ASSERT(!isTrigger(), "unable to create child spans on this context"); - return kj::rc(kj::Badge(), entropySource, traceId, - invocationId, SpanId::fromEntropy(entropySource), addRefToThis()); + kj::Maybe otherEntropySource = entropySource.map( + [](auto& es) -> kj::EntropySource& { return const_cast(es); }); + return InvocationSpanContext(kj::Badge(), otherEntropySource, traceId, + invocationId, SpanId::fromEntropy(otherEntropySource), *this); } -kj::Rc InvocationSpanContext::newForInvocation( - kj::Maybe&> triggerContext, +InvocationSpanContext InvocationSpanContext::newForInvocation( + kj::Maybe triggerContext, kj::Maybe entropySource) { - kj::Maybe> parent; + kj::Maybe parent; auto traceId = triggerContext - .map([&](kj::Rc& ctx) { - parent = ctx.addRef(); - return ctx->traceId; + .map([&](auto& ctx) mutable -> TraceId { + parent = ctx; + return ctx.traceId; }).orDefault([&] { return TraceId::fromEntropy(entropySource); }); - return kj::rc(kj::Badge(), entropySource, - kj::mv(traceId), TraceId::fromEntropy(entropySource), SpanId::fromEntropy(entropySource), - kj::mv(parent)); + return InvocationSpanContext(kj::Badge(), entropySource, kj::mv(traceId), + TraceId::fromEntropy(entropySource), SpanId::fromEntropy(entropySource), kj::mv(parent)); } TraceId TraceId::fromCapnp(rpc::InvocationSpanContext::TraceId::Reader reader) { @@ -214,7 +217,7 @@ void TraceId::toCapnp(rpc::InvocationSpanContext::TraceId::Builder writer) const writer.setHigh(high); } -kj::Maybe> InvocationSpanContext::fromCapnp( +kj::Maybe InvocationSpanContext::fromCapnp( rpc::InvocationSpanContext::Reader reader) { if (!reader.hasTraceId() || !reader.hasInvocationId()) { // If the reader does not have a traceId or invocationId field then it is @@ -222,11 +225,11 @@ kj::Maybe> InvocationSpanContext::fromCapnp( return kj::none; } - auto sc = kj::rc(kj::Badge(), kj::none, + auto sc = InvocationSpanContext(kj::Badge(), kj::none, TraceId::fromCapnp(reader.getTraceId()), TraceId::fromCapnp(reader.getInvocationId()), reader.getSpanId()); // If the traceId or invocationId are invalid, then we'll ignore them. - if (!sc->getTraceId() || !sc->getInvocationId()) return kj::none; + if (!sc.getTraceId() || !sc.getInvocationId()) return kj::none; return kj::mv(sc); } @@ -234,11 +237,18 @@ void InvocationSpanContext::toCapnp(rpc::InvocationSpanContext::Builder writer) traceId.toCapnp(writer.initTraceId()); invocationId.toCapnp(writer.initInvocationId()); writer.setSpanId(spanId); - kj::mv(getParent()); // Just invalidating the parent. Not moving it anywhere. } -kj::String KJ_STRINGIFY(const kj::Rc& context) { - return kj::str(context->getTraceId(), "-", context->getInvocationId(), "-", context->getSpanId()); +InvocationSpanContext InvocationSpanContext::clone() const { + kj::Maybe otherEntropySource = entropySource.map( + [](auto& es) -> kj::EntropySource& { return const_cast(es); }); + return InvocationSpanContext(kj::Badge(), otherEntropySource, traceId, + invocationId, spanId, + parentSpanContext.map([](auto& ctx) -> const InvocationSpanContext& { return *ctx.get(); })); +} + +kj::String KJ_STRINGIFY(const InvocationSpanContext& context) { + return kj::str(context.getTraceId(), "-", context.getInvocationId(), "-", context.getSpanId()); } } // namespace tracing @@ -851,7 +861,7 @@ tracing::Attribute::Attribute(kj::String name, kj::Array&& value) namespace { kj::OneOf> readValues( - rpc::Trace::Attribute::Reader& reader) { + const rpc::Trace::Attribute::Reader& reader) { static auto readValue = [](rpc::Trace::Attribute::Value::Reader reader) -> tracing::Attribute::Value { auto inner = reader.getInner(); @@ -955,7 +965,7 @@ tracing::Attribute tracing::Attribute::clone() { tracing::Return::Return(kj::Maybe info): info(kj::mv(info)) {} namespace { -kj::Maybe readReturnInfo(rpc::Trace::Return::Reader& reader) { +kj::Maybe readReturnInfo(const rpc::Trace::Return::Reader& reader) { auto info = reader.getInfo(); switch (info.which()) { case rpc::Trace::Return::Info::EMPTY: @@ -1015,7 +1025,7 @@ tracing::SpanOpen::SpanOpen(kj::Maybe operationName, kj::Maybe info(kj::mv(info)) {} namespace { -kj::Maybe readSpanOpenOperationName(rpc::Trace::SpanOpen::Reader& reader) { +kj::Maybe readSpanOpenOperationName(const rpc::Trace::SpanOpen::Reader& reader) { if (!reader.hasOperationName()) return kj::none; return kj::str(reader.getOperationName()); } @@ -1144,12 +1154,14 @@ tracing::Onset::Info getInfoFromReader(const rpc::Trace::Onset::Reader& reader) } KJ_UNREACHABLE; } + kj::Maybe getScriptNameFromReader(const rpc::Trace::Onset::Reader& reader) { if (reader.hasScriptName()) { return kj::str(reader.getScriptName()); } return kj::none; } + kj::Maybe> getScriptVersionFromReader( const rpc::Trace::Onset::Reader& reader) { if (reader.hasScriptVersion()) { @@ -1157,12 +1169,14 @@ kj::Maybe> getScriptVersionFromReader( } return kj::none; } + kj::Maybe getDispatchNamespaceFromReader(const rpc::Trace::Onset::Reader& reader) { if (reader.hasDispatchNamespace()) { return kj::str(reader.getDispatchNamespace()); } return kj::none; } + kj::Maybe> getScriptTagsFromReader(const rpc::Trace::Onset::Reader& reader) { if (reader.hasScriptTags()) { auto tags = reader.getScriptTags(); @@ -1174,6 +1188,7 @@ kj::Maybe> getScriptTagsFromReader(const rpc::Trace::Onset } return kj::none; } + kj::Maybe getEntrypointFromReader(const rpc::Trace::Onset::Reader& reader) { if (reader.hasEntryPoint()) { return kj::str(reader.getEntryPoint()); @@ -1326,17 +1341,15 @@ tracing::Outcome tracing::Outcome::clone() { } namespace { -tracing::TailEvent::Context getContextFromSpan( - const kj::Rc& context) { +tracing::TailEvent::Context getContextFromSpan(const tracing::InvocationSpanContext& context) { return tracing::TailEvent::Context( - context->getTraceId(), context->getInvocationId(), context->getSpanId()); + context.getTraceId(), context.getInvocationId(), context.getSpanId()); } kj::Maybe getParentContextFromSpan( - kj::Rc& context) { - return context->getParent().map([](const kj::Rc& context) { - return getContextFromSpan(context); - }); + const tracing::InvocationSpanContext& context) { + return context.getParent().map( + [](const tracing::InvocationSpanContext& context) { return getContextFromSpan(context); }); } } // namespace @@ -1360,7 +1373,7 @@ tracing::TailEvent::Context tracing::TailEvent::Context::clone() { return Context(traceId, invocationId, spanId); } -tracing::TailEvent::TailEvent(kj::Rc& context, +tracing::TailEvent::TailEvent(const tracing::InvocationSpanContext& context, kj::Date timestamp, kj::uint sequence, Event&& event) @@ -1382,18 +1395,18 @@ tracing::TailEvent::TailEvent(Context context, event(kj::mv(event)) {} namespace { -tracing::TailEvent::Context readContextFromTailEvent(rpc::Trace::TailEvent::Reader& reader) { +tracing::TailEvent::Context readContextFromTailEvent(const rpc::Trace::TailEvent::Reader& reader) { return tracing::TailEvent::Context(reader.getContext()); } kj::Maybe readParentContextFromTailEvent( - rpc::Trace::TailEvent::Reader& reader) { + const rpc::Trace::TailEvent::Reader& reader) { if (!reader.hasParentContext()) return kj::none; return tracing::TailEvent::Context(reader.getParentContext()); } -tracing::TailEvent::Event readEventFromTailEvent(rpc::Trace::TailEvent::Reader& reader) { - auto event = reader.getEvent(); +tracing::TailEvent::Event readEventFromTailEvent(const rpc::Trace::TailEvent::Reader& reader) { + const auto event = reader.getEvent(); switch (event.which()) { case rpc::Trace::TailEvent::Event::ONSET: return tracing::Onset(event.getOnset()); diff --git a/src/workerd/io/trace.h b/src/workerd/io/trace.h index 4a34916a7631..bf37df4f0caa 100644 --- a/src/workerd/io/trace.h +++ b/src/workerd/io/trace.h @@ -176,8 +176,7 @@ constexpr SpanId SpanId::nullId = nullptr; // a specific worker invocation. The span id identifies a specific span within an // invocation. Every invocation of every worker should have an InvocationSpanContext. // That may or may not have a trigger InvocationSpanContext. -class InvocationSpanContext final: public kj::Refcounted, - public kj::EnableAddRefToThis { +class InvocationSpanContext final { public: // The constructor is public only so kj::rc can see it and create a new instance. // User code should use the static factory methods or the newChild method. @@ -186,8 +185,16 @@ class InvocationSpanContext final: public kj::Refcounted, TraceId traceId, TraceId invocationId, SpanId spanId, - kj::Maybe> parentSpanContext = kj::none); - KJ_DISALLOW_COPY_AND_MOVE(InvocationSpanContext); + kj::Maybe parentSpanContext = kj::none); + + KJ_DISALLOW_COPY(InvocationSpanContext); + + InvocationSpanContext(InvocationSpanContext&& other) = default; + InvocationSpanContext& operator=(InvocationSpanContext&& other) = default; + + inline bool operator==(const InvocationSpanContext& other) const { + return traceId == other.traceId && invocationId == other.invocationId && spanId == other.spanId; + } inline const TraceId& getTraceId() const { return traceId; @@ -201,14 +208,17 @@ class InvocationSpanContext final: public kj::Refcounted, return spanId; } - inline const kj::Maybe>& getParent() const { - return parentSpanContext; + inline kj::Maybe getParent() const { + KJ_IF_SOME(p, parentSpanContext) { + return *p; + } + return kj::none; } // Creates a new child span. If the current context does not have an entropy // source this will assert. If isTrigger() is true then it will not have an // entropy source. - kj::Rc newChild(); + InvocationSpanContext newChild() const; // An InvocationSpanContext is a trigger context if it has no entropy source. // This generally means the SpanContext was create from a capnp message and @@ -222,36 +232,40 @@ class InvocationSpanContext final: public kj::Refcounted, // traceId is used as the traceId for the newly created context. Otherwise a new // traceId is generated. The invocationId is always generated new and the spanId // will be 0 with no parent span. - static kj::Rc newForInvocation( - kj::Maybe&> triggerContext = kj::none, + static InvocationSpanContext newForInvocation( + kj::Maybe triggerContext = kj::none, kj::Maybe entropySource = kj::none); // Creates a new InvocationSpanContext from a capnp message. The returned // InvocationSpanContext will not be capable of creating child spans and // is considered only a "trigger" span. - static kj::Maybe> fromCapnp( - rpc::InvocationSpanContext::Reader reader); + static kj::Maybe fromCapnp(rpc::InvocationSpanContext::Reader reader); void toCapnp(rpc::InvocationSpanContext::Builder writer) const; + InvocationSpanContext clone() const; private: // If there is no entropy source, then child spans cannot be created from // this InvocationSpanContext. kj::Maybe entropySource; - const TraceId traceId; - const TraceId invocationId; - const SpanId spanId; + TraceId traceId; + TraceId invocationId; + SpanId spanId; // The parentSpanContext can be either a direct parent or a trigger // context. If it is a trigger context, then it should have the same // traceId but a different invocationId (unless predictable mode for // testing is enabled). The isTrigger() should also return true. - const kj::Maybe> parentSpanContext; + kj::Maybe> parentSpanContext; }; kj::String KJ_STRINGIFY(const SpanId& id); kj::String KJ_STRINGIFY(const TraceId& id); -kj::String KJ_STRINGIFY(const kj::Rc& context); +kj::String KJ_STRINGIFY(const InvocationSpanContext& context); +// The various structs defined below are used in both legacy tail workers +// and streaming tail workers to report tail events. + +// Describes a fetch request struct FetchEventInfo final { struct Header; @@ -291,6 +305,7 @@ struct FetchEventInfo final { FetchEventInfo clone(); }; +// Describes a jsrpc request struct JsRpcEventInfo final { explicit JsRpcEventInfo(kj::String methodName); JsRpcEventInfo(rpc::Trace::JsRpcEventInfo::Reader reader); @@ -304,6 +319,7 @@ struct JsRpcEventInfo final { JsRpcEventInfo clone(); }; +// Describes a scheduled request struct ScheduledEventInfo final { explicit ScheduledEventInfo(double scheduledTime, kj::String cron); ScheduledEventInfo(rpc::Trace::ScheduledEventInfo::Reader reader); @@ -318,6 +334,7 @@ struct ScheduledEventInfo final { ScheduledEventInfo clone(); }; +// Describes a Durable Object alarm request struct AlarmEventInfo final { explicit AlarmEventInfo(kj::Date scheduledTime); AlarmEventInfo(rpc::Trace::AlarmEventInfo::Reader reader); @@ -331,6 +348,7 @@ struct AlarmEventInfo final { AlarmEventInfo clone(); }; +// Describes a queue worker request struct QueueEventInfo final { explicit QueueEventInfo(kj::String queueName, uint32_t batchSize); QueueEventInfo(rpc::Trace::QueueEventInfo::Reader reader); @@ -345,6 +363,7 @@ struct QueueEventInfo final { QueueEventInfo clone(); }; +// Describes an email request struct EmailEventInfo final { explicit EmailEventInfo(kj::String mailFrom, kj::String rcptTo, uint32_t rawSize); EmailEventInfo(rpc::Trace::EmailEventInfo::Reader reader); @@ -360,6 +379,7 @@ struct EmailEventInfo final { EmailEventInfo clone(); }; +// Describes a legacy tail worker request struct TraceEventInfo final { struct TraceItem; @@ -389,6 +409,7 @@ struct TraceEventInfo final { TraceEventInfo clone(); }; +// Describes a hibernatable web socket event struct HibernatableWebSocketEventInfo final { struct Message final {}; struct Close final { @@ -412,11 +433,13 @@ struct HibernatableWebSocketEventInfo final { static Type readFrom(rpc::Trace::HibernatableWebSocketEventInfo::Reader reader); }; +// Describes a custom event struct CustomEventInfo final { explicit CustomEventInfo() {}; CustomEventInfo(rpc::Trace::CustomEventInfo::Reader reader) {}; }; +// Describes a fetch response struct FetchResponseInfo final { explicit FetchResponseInfo(uint16_t statusCode); FetchResponseInfo(rpc::Trace::FetchResponseInfo::Reader reader); @@ -430,6 +453,7 @@ struct FetchResponseInfo final { FetchResponseInfo clone(); }; +// Describes an event published using the node:diagnostics_channel API struct DiagnosticChannelEvent final { explicit DiagnosticChannelEvent( kj::Date timestamp, kj::String channel, kj::Array message); @@ -445,6 +469,7 @@ struct DiagnosticChannelEvent final { DiagnosticChannelEvent clone(); }; +// Describes a log event struct Log final { explicit Log(kj::Date timestamp, LogLevel logLevel, kj::String message); Log(rpc::Trace::Log::Reader reader); @@ -463,6 +488,7 @@ struct Log final { Log clone(); }; +// Describes an exception event struct Exception final { explicit Exception( kj::Date timestamp, kj::String name, kj::String message, kj::Maybe stack); @@ -483,6 +509,7 @@ struct Exception final { Exception clone(); }; +// Used to indicate that a previously hibernated tail stream is being resumed. struct Resume final { explicit Resume(kj::Maybe> attachment); Resume(rpc::Trace::Resume::Reader reader); @@ -496,6 +523,7 @@ struct Resume final { Resume clone(); }; +// Used to indicate that a tail stream is being hibernated. struct Hibernate final { explicit Hibernate(); Hibernate(rpc::Trace::Hibernate::Reader reader); @@ -708,6 +736,8 @@ struct TailEvent final { struct Context final { explicit Context(TraceId traceId, TraceId invocationId, SpanId spanId); + Context(const InvocationSpanContext& context) + : Context(context.getTraceId(), context.getInvocationId(), context.getSpanId()) {} Context(rpc::InvocationSpanContext::Reader reader); Context(Context&&) = default; Context& operator=(Context&&) = default; @@ -716,12 +746,22 @@ struct TailEvent final { TraceId invocationId; SpanId spanId; + inline bool operator==(const Context& other) { + return traceId == other.traceId && invocationId == other.invocationId && + spanId == other.spanId; + } + + inline bool operator==(const InvocationSpanContext& other) { + return traceId == other.getTraceId() && invocationId == other.getInvocationId() && + spanId == other.getSpanId(); + } + void copyTo(rpc::InvocationSpanContext::Builder builder); Context clone(); }; explicit TailEvent( - kj::Rc& context, kj::Date timestamp, kj::uint sequence, Event&& event); + const InvocationSpanContext& context, kj::Date timestamp, kj::uint sequence, Event&& event); TailEvent(Context context, kj::Maybe parentContext, kj::Date timestamp, diff --git a/src/workerd/io/worker-entrypoint.c++ b/src/workerd/io/worker-entrypoint.c++ index b12de07e64e1..ad8fa6089e54 100644 --- a/src/workerd/io/worker-entrypoint.c++ +++ b/src/workerd/io/worker-entrypoint.c++ @@ -54,7 +54,7 @@ class WorkerEntrypoint final: public WorkerInterface { bool tunnelExceptions, kj::Maybe> workerTracer, kj::Maybe cfBlobJson, - kj::Maybe> maybeTriggerInvocationSpan); + kj::Maybe maybeTriggerInvocationSpan); kj::Promise request(kj::HttpMethod method, kj::StringPtr url, @@ -98,7 +98,7 @@ class WorkerEntrypoint final: public WorkerInterface { kj::Own ioChannelFactory, kj::Own metrics, kj::Maybe> workerTracer, - kj::Rc invocationSpanContext); + tracing::InvocationSpanContext invocationSpanContext); template kj::Promise maybeAddGcPassForTest(IoContext& context, kj::Promise promise); @@ -161,13 +161,13 @@ kj::Own WorkerEntrypoint::construct(ThreadContext& threadContex bool tunnelExceptions, kj::Maybe> workerTracer, kj::Maybe cfBlobJson, - kj::Maybe> maybeTriggerInvocationSpan) { + kj::Maybe maybeTriggerInvocationSpan) { TRACE_EVENT("workerd", "WorkerEntrypoint::construct()"); // Create a new InvocationSpanContext for this worker invocation. auto invocationSpanContext = tracing::InvocationSpanContext::newForInvocation( maybeTriggerInvocationSpan.map( - [](auto& trigger) -> kj::Rc& { return trigger; }), + [](auto& trigger) -> tracing::InvocationSpanContext& { return trigger; }), threadContext.getEntropySource()); auto obj = kj::heap(kj::Badge(), threadContext, @@ -198,7 +198,7 @@ void WorkerEntrypoint::init(kj::Own worker, kj::Own ioChannelFactory, kj::Own metrics, kj::Maybe> workerTracer, - kj::Rc invocationSpanContext) { + tracing::InvocationSpanContext invocationSpanContext) { TRACE_EVENT("workerd", "WorkerEntrypoint::init()"); // We need to construct the IoContext -- unless this is an actor and it already has a // IoContext, in which case we reuse it. @@ -729,7 +729,7 @@ kj::Own newWorkerEntrypoint(ThreadContext& threadContext, bool tunnelExceptions, kj::Maybe> workerTracer, kj::Maybe cfBlobJson, - kj::Maybe> maybeTriggerInvocationSpan) { + kj::Maybe maybeTriggerInvocationSpan) { return WorkerEntrypoint::construct(threadContext, kj::mv(worker), kj::mv(entrypointName), kj::mv(actor), kj::mv(limitEnforcer), kj::mv(ioContextDependency), kj::mv(ioChannelFactory), kj::mv(metrics), waitUntilTasks, tunnelExceptions, kj::mv(workerTracer), kj::mv(cfBlobJson), diff --git a/src/workerd/io/worker-entrypoint.h b/src/workerd/io/worker-entrypoint.h index d8eec5ad0ae5..a5f4628e736c 100644 --- a/src/workerd/io/worker-entrypoint.h +++ b/src/workerd/io/worker-entrypoint.h @@ -43,6 +43,6 @@ kj::Own newWorkerEntrypoint(ThreadContext& threadContext, // the implication is that this worker entrypoint is being created as a subrequest or // subtask of another request. If it is kj::none, then this invocation is a top-level // invocation. - kj::Maybe> maybeTriggerInvocationSpan = kj::none); + kj::Maybe maybeTriggerInvocationSpan = kj::none); } // namespace workerd