POST /v1/tracesPOST /v1/logsResourceAttributes['cloud.platform'] = 'cloudflare.workers'
ResourceAttributes['cloud.provider'] = 'cloudflare'
cloud.platformcloud.providerservice.namefaas.invocation_idcloudflare.ray_idcloudflare.handler_typecloudflare.entrypointcloudflare.execution_modelcloudflare.outcomecloudflare.cpu_time_mscloudflare.wall_time_msurl.pathhttp.request.methodhttp.response.status_codecloudflare.coloDurationcloudflare.wall_time_mscloudflare.cpu_time_mscloudflare.response.time_to_first_byte_msdb.query.textcloudflare.d1.response.sql_duration_mscloudflare.d1.response.rows_readcloudflare.kv.response.cache_statuscloudflare.r2.operationcloudflare.outcomehttp.response.status_codecloudflare.ray_idGET https://.../routeconsole.error() outputSpiceflow unhandled error: Error: ...exception.* fields.okexceptionexceededCpuexceededMemoryhttps://<project>-ingest.strada.sh/v1/traceshttps://<project>-ingest.strada.sh/v1/logsexample-app-cloudflare/ used to test actual Cloudflare destination export.content-encoding: gzip| Route | What it does | What Cloudflare exported | What matters for Strada |
/ok | healthy request | request trace + request log + app log | baseline shape |
/caught | error caught and converted into HTTP 500 | request trace + request log + app log | not a runtime crash |
/throw | thrown inside Spiceflow route | request trace + request log + framework error log | cloudflare.outcome stayed ok |
/throw-async | async throw inside Spiceflow route | request trace + request log + framework error log | cloudflare.outcome stayed ok |
/crash-runtime | throw before app.handle() in worker fetch() | request trace with cloudflare.outcome = exception + request log + app log | real runtime crash marker |
cloudflare.outcome = exception on the root span.error code: 1101 to the client.exception.typeexception.messageexception.stacktrace$workers.outcome$metadata.errorotel_errors is the trace root span fallback, not logs.wrangler.jsonc{ "name": "my-worker", "main": "src/index.ts", "compatibility_date": "2026-04-23", "observability": { "traces": { "enabled": true, "destinations": ["strada-traces"], "persist": false }, "logs": { "enabled": true, "destinations": ["strada-logs"], "persist": false } } }
/v1/traces and /v1/logs endpoints. The exact full payload shape for Cloudflare-generated uncaught exception logs is not fully documented, but the envelopes are standard OTLP.{ "resourceSpans": [ { "resource": { "attributes": [ { "key": "cloud.provider", "value": { "stringValue": "cloudflare" } }, { "key": "cloud.platform", "value": { "stringValue": "cloudflare.workers" } }, { "key": "service.name", "value": { "stringValue": "my-worker" } }, { "key": "faas.name", "value": { "stringValue": "my-worker" } }, { "key": "cloudflare.colo", "value": { "stringValue": "SFO" } } ] }, "scopeSpans": [ { "spans": [ { "traceId": "4bf92f3577b34da6a3ce929d0e0e4736", "spanId": "00f067aa0ba902b7", "name": "fetch", "kind": 1, "startTimeUnixNano": "1713890000000000000", "endTimeUnixNano": "1713890000200000000", "attributes": [ { "key": "faas.trigger", "value": { "stringValue": "http" } }, { "key": "cloudflare.ray_id", "value": { "stringValue": "87d3abc123" } }, { "key": "cloudflare.handler_type", "value": { "stringValue": "fetch" } }, { "key": "cloudflare.outcome", "value": { "stringValue": "ok" } }, { "key": "cloudflare.cpu_time_ms", "value": { "doubleValue": 12 } }, { "key": "cloudflare.wall_time_ms", "value": { "doubleValue": 48 } }, { "key": "url.full", "value": { "stringValue": "https://example.com/api/users?id=1" } }, { "key": "url.path", "value": { "stringValue": "/api/users" } }, { "key": "http.request.method", "value": { "stringValue": "GET" } }, { "key": "http.response.status_code", "value": { "intValue": "200" } } ] } ] } ] } ] }
exception.* attributes.{ "resourceLogs": [ { "resource": { "attributes": [ { "key": "cloud.provider", "value": { "stringValue": "cloudflare" } }, { "key": "cloud.platform", "value": { "stringValue": "cloudflare.workers" } }, { "key": "service.name", "value": { "stringValue": "my-worker" } } ] }, "scopeLogs": [ { "logRecords": [ { "timeUnixNano": "1713890000100000000", "severityText": "ERROR", "body": { "stringValue": "Spiceflow unhandled error: Error: uncaught cloudflare validation error" }, "attributes": [ { "key": "cloudflare.ray_id", "value": { "stringValue": "87d3abc123" } } ] } ] } ] } ] }
WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers'
SpanAttributes['cloudflare.handler_type']SpanAttributes['cloudflare.entrypoint']SpanAttributes['cloudflare.execution_model']SpanAttributes['cloudflare.outcome']SpanAttributes['url.path']SpanAttributes['http.request.method']url.pathhttp.request.methodDurationcloudflare.wall_time_mscloudflare.cpu_time_msfetch, or Durable Object storage.cloudflare.outcome = 'exception'TraceIddb.system.namedb.operation.namecloudflare.d1.response.sql_duration_mscloudflare.jsrpc.methodcloudflare.entrypointcloudflare.outcomeSELECT Timestamp, ServiceName, SpanName, SpanAttributes['cloudflare.outcome'] AS outcome, SpanAttributes['cloudflare.handler_type'] AS handler_type, SpanAttributes['cloudflare.entrypoint'] AS entrypoint, SpanAttributes['cloudflare.ray_id'] AS ray_id FROM otel_traces WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers' AND SpanAttributes['cloudflare.outcome'] != 'ok' ORDER BY Timestamp DESC LIMIT 100
SELECT Timestamp, ServiceName, SpanName, Duration, SpanAttributes['http.request.method'] AS method, SpanAttributes['url.path'] AS path, SpanAttributes['cloudflare.cpu_time_ms'] AS cpu_ms, SpanAttributes['cloudflare.wall_time_ms'] AS wall_ms FROM otel_traces WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers' AND SpanAttributes['cloudflare.handler_type'] = 'fetch' ORDER BY Duration DESC LIMIT 100
SELECT Timestamp, ServiceName, SpanName, TraceId, SpanAttributes['cloudflare.handler_type'] AS handler_type, SpanAttributes['cloudflare.entrypoint'] AS entrypoint, SpanAttributes['cloudflare.ray_id'] AS ray_id FROM otel_traces WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers' AND SpanAttributes['cloudflare.outcome'] = 'exception' ORDER BY Timestamp DESC LIMIT 100
SELECT Timestamp, ServiceName, SpanName, SpanAttributes['db.operation.name'] AS operation, SpanAttributes['cloudflare.d1.response.sql_duration_ms'] AS sql_ms, SpanAttributes['cloudflare.d1.response.rows_read'] AS rows_read, SpanAttributes['cloudflare.d1.response.rows_written'] AS rows_written FROM otel_traces WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers' AND SpanAttributes['cloudflare.binding.type'] = 'd1' ORDER BY toFloat64OrZero(SpanAttributes['cloudflare.d1.response.sql_duration_ms']) DESC LIMIT 100
SELECT Timestamp, ServiceName, SeverityText, Body, TraceId, LogAttributes['cloudflare.ray_id'] AS ray_id FROM otel_logs WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers' AND TraceId = '<trace-id-from-failing-root-span>' ORDER BY Timestamp DESC LIMIT 100
exception.* fields. Query them separately when needed:SELECT Timestamp, ServiceName, SeverityText, Body, TraceId, LogAttributes['exception.type'] AS exception_type, LogAttributes['exception.message'] AS exception_message FROM otel_logs WHERE ResourceAttributes['cloud.platform'] = 'cloudflare.workers' AND ( mapContains(LogAttributes, 'exception.type') OR mapContains(LogAttributes, 'exception.message') ) ORDER BY Timestamp DESC LIMIT 100
cloud.providercloudflare.ResourceAttributes['cloud.provider'] = 'cloudflare'
cloud.platformcloudflare.workers.ResourceAttributes['cloud.platform'] = 'cloudflare.workers'
faas.nameservice.name when normalizing service identity.faas.invocation_idfaas.versionfaas.invoked_regionservice.nameServiceName = 'my-worker'
cloudflare.coloSFO or LHR.cloudflare.script_nameservice.name.cloudflare.script_tagscloudflare.script_version.idcloudflare.invocation.sequence.numbertelemetry.sdk.languagejavascript.telemetry.sdk.namecloudflare.faas.triggerhttp, cron, queue, or email.cloudflare.ray_idcloudflare.handler_typefetch, scheduled, queue, email, or alarm.cloudflare.entrypointcloudflare.execution_modelstateless or stateful.cloudflare.outcomeok, exception, exceededCpu, or exceededMemory.SpanAttributes['cloudflare.outcome'] = 'exception'
cloudflare.cpu_time_mscloudflare.wall_time_msnetwork.protocol.namenetwork.protocol.versionurl.fullurl.schemehttps.url.pathurl.queryserver.portfetch() spans.server.addressuser_agent.originalhttp.request.methodGET or POST.http.request.header.content-typehttp.request.header.content-lengthhttp.request.header.acceptAccept header.http.request.header.accept-encodingAccept-Encoding header.http.request.body.sizehttp.response.status_codehttp.response.body.sizecloudflare.verified_bot_categorycloudflare.asncloudflare.response.time_to_first_byte_msgeo.timezonegeo.continent.codegeo.country.codegeo.locality.namegeo.locality.regionuser_agent.os.nameuser_agent.os.versionuser_agent.browser.nameuser_agent.browser.major_versionuser_agent.browser.versionuser_agent.engine.nameuser_agent.engine.versionuser_agent.device.typemobile or desktop.user_agent.device.vendoruser_agent.device.modelhttp.request.header.accept-languageAccept-Language header.faas.croncloudflare.scheduled_timecloudflare.queue.namecloudflare.queue.batch_sizecloudflare.jsrpc.methodcloudflare.email.fromcloudflare.email.tocloudflare.email.sizecloudflare.trace.countcache.request.urlcache.request.methodcache.request.payload.status_codecache.request.payload.header.cache_controlcache.request.payload.header.cache_tagcache.request.payload.header.etagcache.request.payload.header.expirescache.request.payload.header.last_modifiedcache.request.payload.sizecache.response.successcache.request.ignore_methodcache.request.header.rangecache.request.header.if_modified_sincecache.request.header.if_none_matchcache.response.body.sizecache.response.cache_statuscache.response.status_codedb.system.namedb.operation.namedb.query.textcloudflare.binding.typecloudflare.d1.response.size_aftercloudflare.d1.response.rows_readcloudflare.d1.response.rows_writtencloudflare.d1.response.last_row_idcloudflare.d1.response.changed_dbcloudflare.d1.response.changescloudflare.d1.response.served_by_regioncloudflare.d1.response.served_by_primarycloudflare.d1.response.sql_duration_mscloudflare.d1.response.total_attemptsdb.operation.batch.sized1_batch.cloudflare.d1.query.bookmarkcloudflare.d1.response.bookmarkcloudflare.binding.namecloudflare.kv.query.keyscloudflare.kv.query.keys.countcloudflare.kv.query.typecloudflare.kv.query.cache_ttlcloudflare.kv.response.sizecloudflare.kv.response.returned_rowscloudflare.kv.response.metadatacloudflare.kv.response.cache_statuscloudflare.kv.query.value_typecloudflare.kv.query.expirationcloudflare.kv.query.expiration_ttlcloudflare.kv.query.metadatacloudflare.kv.query.payload.sizecloudflare.kv.query.prefixcloudflare.kv.query.limitcloudflare.kv.query.cursorcloudflare.kv.response.list_completecloudflare.kv.response.cursorcloudflare.kv.response.expirationcloudflare.r2.bucketcloudflare.r2.operationcloudflare.r2.response.successcloudflare.r2.error.messagecloudflare.r2.error.codecloudflare.r2.request.keycloudflare.r2.response.etagcloudflare.r2.response.sizecloudflare.r2.response.uploadedcloudflare.r2.response.checksum.valuecloudflare.r2.response.checksum.typecloudflare.r2.response.storage_classcloudflare.r2.response.ssec_keycloudflare.r2.response.content_typecloudflare.r2.response.content_encodingcloudflare.r2.response.content_dispositioncloudflare.r2.response.content_languagecloudflare.r2.response.cache_controlcloudflare.r2.response.cache_expirycloudflare.r2.response.custom_metadatacloudflare.r2.request.range.offsetcloudflare.r2.request.range.lengthcloudflare.r2.request.range.suffixcloudflare.r2.request.rangecloudflare.r2.request.ssec_keycloudflare.r2.request.only_if.etag_matchescloudflare.r2.request.only_if.etag_does_not_matchcloudflare.r2.request.only_if.uploaded_beforecloudflare.r2.request.only_if.uploaded_aftercloudflare.r2.request.sizecloudflare.r2.request.checksum.typecloudflare.r2.request.checksum.valuecloudflare.r2.request.custom_metadatacloudflare.r2.request.http_metadata.content_typecloudflare.r2.request.http_metadata.content_encodingcloudflare.r2.request.http_metadata.content_dispositioncloudflare.r2.request.http_metadata.content_languagecloudflare.r2.request.http_metadata.cache_controlcloudflare.r2.request.http_metadata.cache_expirycloudflare.r2.request.storage_classcloudflare.r2.request.limitcloudflare.r2.request.prefixcloudflare.r2.request.cursorcloudflare.r2.request.delimitercloudflare.r2.request.start_aftercloudflare.r2.request.include.http_metadatacloudflare.r2.request.include.custom_metadatacloudflare.r2.response.returned_objectscloudflare.r2.response.delimited_prefixescloudflare.r2.response.truncatedcloudflare.r2.response.cursorcloudflare.r2.request.keyscloudflare.r2.response.upload_idcloudflare.r2.request.upload_idcloudflare.r2.request.part_numbercloudflare.r2.request.uploaded_partscloudflare.durable_object.query.bindingscloudflare.durable_object.response.rows_readcloudflare.durable_object.response.rows_writtencloudflare.durable_object.response.db_sizecloudflare.durable_object.kv.query.keyscloudflare.durable_object.kv.query.keys.countcloudflare.durable_object.kv.response.deleted_countcloudflare.durable_object.kv.query.startcloudflare.durable_object.kv.query.startAftercloudflare.durable_object.kv.query.endcloudflare.durable_object.kv.query.prefixcloudflare.durable_object.kv.query.reversecloudflare.durable_object.kv.query.limitcloudflare.images.options.formatcloudflare.images.options.qualitycloudflare.images.options.backgroundcloudflare.images.options.animcloudflare.images.options.transformscloudflare.images.error.codecloudflare.images.options.encodingcloudflare.images.result.formatcloudflare.images.result.file_sizecloudflare.images.result.widthcloudflare.images.result.heightconsole.log() outputexception.typeexception.messageexception.stacktracecloudflare.outcomeexception.* existscloud.platform = 'cloudflare.workers'cloudflare.handler_typecloudflare.entrypointcloudflare.outcomecloudflare.cpu_time_mscloudflare.wall_time_msfetch, or Durable Object workexception.*