Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test scaffolding and DO storage instrumentation tests #35

Open
wants to merge 188 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
91e51c4
add a example queue producer/consumer
evanderkoogh Apr 2, 2023
2f79b3f
make relative import to make sure we test with latest version
evanderkoogh Apr 3, 2023
d78a860
Refactor: Extract all instrumentation into its own folder and config …
evanderkoogh Apr 3, 2023
3791f61
first cut at queues
evanderkoogh Apr 3, 2023
fd741fb
fix: didn't handle passing in attributes, but no time properly
evanderkoogh Apr 3, 2023
094d05b
0.0.6
evanderkoogh Apr 3, 2023
7f19ae0
fix import
evanderkoogh Apr 3, 2023
a5242ec
prevent double reporting when `.end()` is called multiple times
evanderkoogh Apr 3, 2023
c1a359d
add message statistics to the top batch span.
evanderkoogh Apr 3, 2023
b130296
0.0.7
evanderkoogh Apr 3, 2023
3b81ddd
rename proxy* to instrument*
evanderkoogh Apr 3, 2023
b26d331
add support for auto-instrumenting queue sending
evanderkoogh Apr 3, 2023
239f389
small cleanup
evanderkoogh Apr 3, 2023
38de195
0.0.8
evanderkoogh Apr 3, 2023
b17bb4d
add types
evanderkoogh Apr 3, 2023
cd5c3fc
add overview of what components are instrumented and which ones aren'…
evanderkoogh Apr 3, 2023
6ee9d9e
0.1.0
evanderkoogh Apr 3, 2023
7abd607
small refactor
evanderkoogh Apr 3, 2023
cd9b337
Utility to make it easy to create a trace for a waitUntil promise.
evanderkoogh Apr 3, 2023
0692177
0.1.1
evanderkoogh Apr 3, 2023
6ea9bf6
Take exporting traces out of the critical path. Send with `.waitUntil`
evanderkoogh Apr 4, 2023
1d547b0
don't export if there are no spans to be exported
evanderkoogh Apr 4, 2023
4f25827
Can strike out the limitation about extra latency
evanderkoogh Apr 4, 2023
64fe894
0.2.0
evanderkoogh Apr 4, 2023
05634fa
Refactoring config.
evanderkoogh Apr 4, 2023
98f084f
0.2.1
evanderkoogh Apr 4, 2023
87abb30
delete log line
evanderkoogh Apr 4, 2023
4a0e4b9
Replace ugly duplicate globals hack with dignified proxies..
evanderkoogh Apr 5, 2023
129186c
add warning for potentially sensitive data
evanderkoogh Apr 5, 2023
eb6fa02
move sanitiseURL to ./common
evanderkoogh Apr 5, 2023
4e0df09
First cut of cache instrumentation
evanderkoogh Apr 5, 2023
83b48c6
add config as parameter to make things consistent
evanderkoogh Apr 5, 2023
878b5e6
export isWrapped now
evanderkoogh Apr 5, 2023
ef4d948
add cache example
evanderkoogh Apr 5, 2023
0f9fd62
rework caching logic to fix Proxy issues
evanderkoogh Apr 5, 2023
9a84672
Automatically instrument the global caches object.
evanderkoogh Apr 5, 2023
001e613
add caches tick :)
evanderkoogh Apr 5, 2023
c8012e7
0.2.2
evanderkoogh Apr 5, 2023
756ec3e
execute both KV and cache in parallel to see if that works properly
evanderkoogh Apr 5, 2023
234cfb6
Reworked the entire config handling to use Zod and deepmerge
evanderkoogh Apr 7, 2023
e547b1c
Refactor: Move instrumentation of global fetch and caches to a global…
evanderkoogh Apr 7, 2023
9a15aa9
remove logging
evanderkoogh Apr 7, 2023
2bb1ed6
Simple configuration options for global fetch and cache instrumentation
evanderkoogh Apr 7, 2023
4eeb735
Add config for sanitising KV keys to example config
evanderkoogh Apr 11, 2023
c389580
only pass through relevant parts of the config
evanderkoogh Apr 11, 2023
27d587f
Add kv specific configuration options & extended auto-instrumentation
evanderkoogh Apr 11, 2023
88ae95e
fix header configuration example after recent change
evanderkoogh Apr 11, 2023
04f54a6
0.2.3
evanderkoogh Apr 11, 2023
7264620
potential fix for multiple subsequent request to the same isolate not…
evanderkoogh Apr 11, 2023
157dc3e
0.2.4
evanderkoogh Apr 11, 2023
a377ac2
refactor out KV instrumentation to its own file
evanderkoogh Apr 11, 2023
51603d7
expand with a DO case
evanderkoogh Apr 12, 2023
ea17ec5
make more robust in face of proxying proxies that are undefined.. or …
evanderkoogh Apr 12, 2023
d4f0bc9
refactoring the global fetch instrumentation into a generic "fetcher"…
evanderkoogh Apr 12, 2023
5c31c14
add initial DO binding support
evanderkoogh Apr 12, 2023
bc684ee
0.2.5
evanderkoogh Apr 12, 2023
6c47a0e
export more fetchHandler related functions
evanderkoogh Apr 13, 2023
c01de67
first cut of the Durable Object auto-instrumentation
evanderkoogh Apr 13, 2023
42c6a8f
0.2.6
evanderkoogh Apr 13, 2023
92b99bb
make service.version optional
evanderkoogh Apr 15, 2023
08f6708
make interface less picky about what Env should be to make it easier …
evanderkoogh Apr 15, 2023
a49c0d2
add DO specific config to specify different service name.
evanderkoogh Apr 15, 2023
3a841d9
0.2.7
evanderkoogh Apr 15, 2023
e495934
Add auto-instrumentation section with more detailed examples
evanderkoogh Apr 16, 2023
a4c366e
Taking us out of alpha into beta!
evanderkoogh Apr 16, 2023
6dbf6c3
auto-set spans to correct status when known.
evanderkoogh Apr 16, 2023
9508660
0.8.1
evanderkoogh Apr 16, 2023
e640d2d
fix config error
evanderkoogh Apr 19, 2023
07f6bce
make config declaration more readable & print errors
evanderkoogh Apr 19, 2023
a04dcbe
start of refactor to rework how config is resolved & root spans are c…
evanderkoogh Apr 19, 2023
443589b
Start to rework the way we load config and take it from the context.
evanderkoogh Apr 22, 2023
0ae15be
Move exporting the spans out of the critical path.
evanderkoogh Apr 22, 2023
73b8b90
0.8.2
evanderkoogh Apr 22, 2023
0547109
remove no longer needed imports
evanderkoogh Apr 22, 2023
ec89ee3
Cleaning up with Parameters<> utility type rather than hardcode
evanderkoogh Apr 22, 2023
edd4f5a
moving to config in context, rather than passing along
evanderkoogh Apr 22, 2023
ef57c01
last bit of the configuration/initialisation migration
evanderkoogh Apr 22, 2023
18ad3ef
rename instrumentDurableObject to instrumentDOBinding
evanderkoogh Apr 22, 2023
0ac5247
0.8.3
evanderkoogh Apr 22, 2023
76cf223
split up globals into cache.ts and fetch.ts
evanderkoogh Apr 22, 2023
71bbbe6
oops..
evanderkoogh Apr 22, 2023
d50d23d
Cleaning up and bringing things into line with latest patterns
evanderkoogh Apr 23, 2023
5bddbc6
fix bug that was introduced with new config scheme that never instrum…
evanderkoogh Apr 23, 2023
2de4e87
tighten up exports
evanderkoogh Apr 23, 2023
7fb6d80
use the function style of config passing
evanderkoogh Apr 23, 2023
69d5c2d
add parseConfig function
evanderkoogh Apr 23, 2023
5956a09
add utility functions for triggers
evanderkoogh Apr 23, 2023
af0a5ed
0.8.4
evanderkoogh Apr 23, 2023
d409782
0.9.0
evanderkoogh Apr 23, 2023
1a42747
adding support for Durable Object alarms
evanderkoogh Apr 24, 2023
c8d42a4
0.9.1
evanderkoogh Apr 24, 2023
34700b4
slim down library somewhat by relying less on unused OTel implementat…
evanderkoogh Apr 25, 2023
a0fe3ad
renamed isChildSpan to hasParentContext to be more clear
evanderkoogh May 6, 2023
8683981
complete rewrite of the SpanProcessor to keep track of entire spans t…
evanderkoogh May 6, 2023
b26a052
add setConfig method to be more in line with other APIs.. looking to …
evanderkoogh May 6, 2023
68a76c8
Bring back FlushOnlySpanProcessor back from the dead for now
evanderkoogh May 7, 2023
8a90185
move wrap functionality out of common and into wrap.ts
evanderkoogh May 26, 2023
db3befa
move exportSpans to common
evanderkoogh May 26, 2023
82b0dcf
move over all queue instrumentation to the instrumentation queue module
evanderkoogh May 26, 2023
5b28f97
refactor for readability
evanderkoogh May 26, 2023
da114a7
readability refactor
evanderkoogh May 27, 2023
7e9dc04
cleanup
evanderkoogh May 27, 2023
d4f82a9
removed in favour of setConfig/withContext combo
evanderkoogh May 28, 2023
f345eb6
add a passthroughGet option that properly binds this to any functions
evanderkoogh May 28, 2023
48b0697
massive refactor to move all the DO related instrumentation to the "d…
evanderkoogh May 28, 2023
b0ac407
improve readability
evanderkoogh May 29, 2023
20a9f89
More readability improvements
evanderkoogh May 29, 2023
21a0e0c
move over to the new BatchTraceSpanProcessor
evanderkoogh Jun 7, 2023
871e6ce
break up handler logic and instrumentation configuration into separat…
evanderkoogh Jun 9, 2023
f6f32d3
Overhaul of the configuration system. Remove zod and automatic enviro…
evanderkoogh Jun 9, 2023
3fc6b5f
add sanitiser support to sanitise anything in the about to exported s…
evanderkoogh Jun 9, 2023
d42b70a
No longer need the FlushOnlySpanProcessor
evanderkoogh Jun 9, 2023
9c63bbe
cleanup
evanderkoogh Jun 9, 2023
61adb97
Next step of config overhaul, colocate all config with their function…
evanderkoogh Jun 9, 2023
bd2a967
Changed mind about initialiser, moved back to config
evanderkoogh Jun 9, 2023
3a0632a
No longer *need* waitUntilTrace
evanderkoogh Jun 11, 2023
cb0c478
Some sort of sampling support, but certainly not final yet.
evanderkoogh Jun 11, 2023
a5d82c4
remove console.logs
evanderkoogh Jun 11, 2023
3aec302
add alpha warning
evanderkoogh Jun 11, 2023
a131af9
1.0.0-alpha.0
evanderkoogh Jun 11, 2023
12c1327
Catch errors before version, rather than before publish
evanderkoogh Jun 11, 2023
7bf3fdd
Change type WorkerTraceConfig to new ResolvedTraceConfig
evanderkoogh Jun 11, 2023
7bd2b82
1.0.0-alpha.1
evanderkoogh Jun 11, 2023
ff9b602
remove zod as a dependency
evanderkoogh Jun 11, 2023
db55002
remove another console.log
evanderkoogh Jun 11, 2023
67310c1
Allow gets on the returned fetch function
evanderkoogh Jun 11, 2023
53e2f2a
1.0.0-alpha.2
evanderkoogh Jun 11, 2023
b846dab
If no `get` handler is registered, we will automatically pass gets th…
evanderkoogh Jun 11, 2023
d426142
1.0.0-alpha.3
evanderkoogh Jun 11, 2023
0ce1f83
Workaround for https://github.com/cloudflare/workers-sdk/issues/3478
evanderkoogh Jun 16, 2023
9b40f78
1.0.0-alpha.4
evanderkoogh Jun 16, 2023
ef3903d
Properly awaiting exports now.
evanderkoogh Jun 20, 2023
0adc72b
1.0.0-alpha.5
evanderkoogh Jun 20, 2023
362c2ec
ignore .wrangler
evanderkoogh Jun 21, 2023
af9e66b
cleanup
evanderkoogh Jun 21, 2023
fb6931d
update error
evanderkoogh Jun 21, 2023
1fffc93
Handle undefined env vars
lboynton Jun 29, 2023
8c6290c
Merge pull request #10 from lboynton/patch-1
evanderkoogh Jun 30, 2023
08bc79b
No longer need to turn off tracing for components with postProcessing
evanderkoogh Jun 30, 2023
1f0c2c4
cleanup
evanderkoogh Jun 30, 2023
bc6281b
fix nested waitUntils
hansottowirtz Jun 16, 2023
050eade
Add license and homepage
evanderkoogh Jun 30, 2023
4124a39
Fix homepage :)
lboynton Jun 30, 2023
da610f5
Fix Homepage
evanderkoogh Jul 1, 2023
0da125a
Merge pull request #8 from hansottowirtz/fix-nested-wait-untils
evanderkoogh Jul 1, 2023
31ce29c
Finish sampling and reworking config
evanderkoogh Jul 1, 2023
02c0151
Move span attributes to earlier to make sure they are available to th…
evanderkoogh Jul 1, 2023
918e334
1.0.0-alpha.6
evanderkoogh Jul 1, 2023
4c95066
Make it easy to do ratio based headSampling
evanderkoogh Jul 2, 2023
5ec44e4
type fix
evanderkoogh Jul 2, 2023
3348c9e
1.0.0-rc.0
evanderkoogh Jul 2, 2023
d4e8f6d
rename postProcessorFn to just postProcessor
evanderkoogh Jul 3, 2023
849995c
Move up fetch configuration up a level instead of globals
evanderkoogh Jul 3, 2023
f4d66bd
Updated the README with a full description of the new configuration o…
evanderkoogh Jul 3, 2023
efbd35e
1.0.0-rc.1
evanderkoogh Jul 3, 2023
3d5288e
update queue example to latest library version
evanderkoogh Jul 3, 2023
dcccbd8
cleanup
evanderkoogh Jul 3, 2023
4047996
Handle `null` the same as `undefined`
evanderkoogh Jul 3, 2023
6f0a529
Improve readability
evanderkoogh Jul 4, 2023
4b7a6ea
Implement Durable Object storage auto-instrumenting
evanderkoogh Jul 4, 2023
9f5aaba
1.0.0-rc.2
evanderkoogh Jul 4, 2023
644f303
no longer need traceId to export
evanderkoogh Jul 5, 2023
b42b5c9
Handle the case where blockConcurrencyWhile is called inside a constr…
evanderkoogh Jul 5, 2023
a5e8221
add note about adding node_compat flag to wrangler.toml
evanderkoogh Jul 6, 2023
0333acd
Move the build over to a dual CommonJS and ESM build
evanderkoogh Jul 6, 2023
51feea8
1.0.0-rc.3
evanderkoogh Jul 6, 2023
41d4ec4
Bring in idGenerator from OTel to make sure users can't pick the node…
evanderkoogh Jul 6, 2023
7ff5912
remove console.log
evanderkoogh Jul 6, 2023
c7d16ab
1.0.0-rc.4
evanderkoogh Jul 6, 2023
a1b7cb6
Put Buffer in the global scope
evanderkoogh Jul 6, 2023
99300ae
Revert "Bring in idGenerator from OTel to make sure users can't pick …
evanderkoogh Jul 6, 2023
7560e1d
1.0.0-rc.5
evanderkoogh Jul 6, 2023
feafed0
forgot to add .js to the implicit imports from index.js
evanderkoogh Jul 6, 2023
df72663
1.0.0-rc.6
evanderkoogh Jul 6, 2023
6d78a57
More .js additions to the imports
evanderkoogh Jul 8, 2023
979d069
fixed includeTraceParent resolving
rtbenfield Jul 13, 2023
0c224c0
adding faas.execution attribute from cf-ray
rtbenfield Jul 13, 2023
b09bef6
Merge pull request #24 from rtbenfield/fix-includeTraceContext
evanderkoogh Jul 14, 2023
3289d38
adding configuration for fetch handler
rtbenfield Jul 15, 2023
812e445
Fix CJS types issues
yacinehmito Jul 19, 2023
5754233
fix storage.list with no args
rtbenfield Jul 23, 2023
75d1633
Merge pull request #27 from rtbenfield/faas-execution
evanderkoogh Jul 24, 2023
81e837f
Merge pull request #28 from rtbenfield/configure-accept-trace-context
evanderkoogh Jul 24, 2023
b9ba407
Merge pull request #30 from yacinehmito/main
evanderkoogh Jul 24, 2023
4a89752
Merge pull request #32 from rtbenfield/fix-do-storage-list
evanderkoogh Jul 24, 2023
b0f344a
do-storage tests
rtbenfield Jul 26, 2023
eae3995
adding pull_request_target trigger
rtbenfield Jul 26, 2023
0fe2faa
renamed workflow
rtbenfield Jul 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: PR
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
pull_request:
branches: [main]
pull_request_target:
branches: [main]

jobs:
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
- name: Restore dependencies
run: npm ci
- name: Run tests
run: npm test:coverage
259 changes: 242 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,269 @@

An OpenTelemetry compatible library for instrumenting and exporting traces from Cloudflare Workers.

> **Warning**
> This package is still in alpha. It has not been tested extensively, optimisations have not yet been made, and the API interface and the configuration options are subject to change.

## Getting started

To be able to use the Open Telemetry library you have to add the NodeJS compatibility flag in your `wrangler.toml` file.

```
compatibility_flags = [ "nodejs_compat" ]
```

### Code example

```typescript
import { trace } from '@opentelemetry/api'
import { instrument, WorkerTraceConfig } from '@microlabs/otel-cf-worker'
import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers'

export interface Env {
HONEYCOMB_API_KEY: string
OTEL_TEST: KVNamespace
}

const handler = {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
await fetch('https://cloudflare.com')

const greeting = "G'day World"
trace.getActiveSpan()?.setAttribute('greeting', greeting)
return new Response(`G'day World!`)
ctx.waitUntil(fetch('https://workers.dev'))
return new Response(`${greeting}!`)
},
}

const config: WorkerTraceConfig = {
exporter: { url: 'https://api.honeycomb.io/v1/traces' },
serviceName: 'greetings',
serviceVersion: '0.1',
const config: ResolveConfigFn = (env: Env, _trigger) => {
return {
exporter: {
url: 'https://api.honeycomb.io/v1/traces',
headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
},
service: { name: 'greetings' },
}
}

export default instrument(handler, config)
```

If you need to send an API token to your Open Telemetry provider of your choice, you can either add a `headers` object in the exporter part of the configuration (not recommended), or set it was an environment secret in the form: `otel.headers.<header_name>` with the API token as the value.
## Auto-instrumentation

So for Honeycomb for example, the environment variable would be: `otel.headers.x-honeycomb-team`.
Any other headers that you need to send through can be configured in either the config object or through environment variables.
### Workers

## Auto-instrumentation
Wrapping your exporter handler with the `instrument` function is all you need to do to automatically have not just the functions of you handler auto-instrumented, but also the global `fetch` and `caches` and all of the supported bindings in your environment such as KV.

See the quick start code sample for an example of how it works.

### Durable Objects

Instrumenting Durable Objects work very similar to the regular Worker auto-instrumentation. Instead of wrapping the handler in an `instrument` call, you wrap the Durable Object class with the `instrumentDO` function.

```typescript
import { instrumentDO, PartialTraceConfig } from '@microlabs/otel-cf-workers'

const config: ResolveConfigFn = (env: Env, _trigger) => {
return {
exporter: {
url: 'https://api.honeycomb.io/v1/traces',
headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
},
service: { name: 'greetings-do' },
}
}

class OtelDO implements DurableObject {
async fetch(request: Request): Promise<Response> {
return new Response('Hello World!')
}
}

const TestOtelDO = instrumentDO(OtelDO, doConfig)

export { TestOtelDO }
```

## Creating custom spans

While auto-instrumenting should take care of a lot of the information that you would want to add, there will always be application specific information you want to send along.

You can get the current active span by doing:

```typescript
import {trace} from '@opentelemetry/api'

const handler = {
async fetch(request: Request) {
const span = trace.getActiveSpan()
if(span) span.setAttributes('name', 'value')
....
}
}
```

Or if you want to create a new span:

```typescript
import { trace } from '@opentelemetry/api'

const handler = {
async fetch(request: Request) {
const tracer = trace.getTracer('my_own_tracer_name')
return tracer.startActiveSpan('name', (span) => {
const response = await doSomethingAwesome
span.end()
return response
})
},
}
```

## Configuration

For configuration you can either pass in a [TraceConfig](https://github.com/evanderkoogh/otel-cf-workers/blob/0da125a4e16ff13e49f8e486340eb6080e631eb9/src/types.ts#L24C18-L24C29) or a function that takes the Environment and the trigger for this particular trace and returns a `TraceConfig`.

Because the configuration function is run separately for every new invocation, it is possible to tailor your configuration for every type of request. So it is for example possible to have a much lower sampling ratio for your healthchecks than actual API requests.

### Exporter

In the `exporter`, you need to configure where to send spans to. It can take either an instance of a class that implements the standard Open Telemetry `SpanExporter`interface, or an object with the properties `url` and optionally `headers` to configure an exporter for the Open Telemetry format.

Examples:

```typescript
const exporter = new ConsoleSpanExporter()
```

```typescript
const exporter = {
url: 'https://api.honeycomb.io/v1/traces',
headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
}
```

### Fetch

`includeTraceContext` is used to specify if outgoing requests should include the TraceContext so that the other service can participate in a distributed trace.
The default is `true` for all outgoing requests, but you can turn it off for all requests with `false`, or specify a method that takes the outgoing `Request` method and return a boolean on whether to include the tracing context.

Currently only the fetch handler, outgoing `fetch` and KV bindings are auto-instrumented. The plan is to add support for all handlers (such as cron triggers or queue messages) and binding types (such as Durable Objects)
Example:

```typescript
const fetchConf = (request: Request): boolean => {
return new URL(request.url).hostname === 'example.com'
}
```

### Handlers

The `handlers` field of the configuration overrides the way in which event handlers, such as `fetch` or `queue`, are instrumented.

#### Fetch Handler

`acceptTraceContext` is used to specify if incoming requests handled by `fetch` should accept a TraceContext and participate in a distributed trace.
The default is `true` for all incoming requests, but you can turn it off for all requests with `false` or specify a method that takes the incoming `Request` and returns a boolean indicating whether to accept the tracing context.

Example:

```typescript
const fetchConf = (request: Request): boolean => {
return new URL(request.url).hostname === 'example.com'
}
```

### PostProcessor

The PostProcessor function is called just before exporting the spans and allows you to make any changes to the spans before sending this. For example to remove entire spans, or to remove or redact security or privacy sensitive data.

Example:

```typescript
const postProcessor = (spans: ReadableSpan[]): ReadableSpan[] => {
spans[0].attributes['http.url'] = 'REDACTED'
return spans
}
```

### Sampling

One of the challenges of tracing is that for sites and applications with a lot of traffic it becomes prohibitively expensive to store every trace. So the question becomes how to store the ones with the most interesting information and drop the ones that are the least interesting. That is where sampling comes in.

#### Head Sampling vs Tail Sampling

There are two (complimentary) sampling strategies: Head Sampling and Tail Sampling and in a lot of cases you will want to use a combination to get the most information into the least amount of sampled events.

To understand the difference in head vs tail sampling in our context, we have to understand distributed tracing. A distributed trace is one that spans multiple systems or services. At every point another service is called, we inject a header with the information about the trace, such as the traceId, the parentSpanId and a hint if this trace is sampled.

Head Sampling, as the name implies, is done at the beginning of a span/trace. In our case it is mostly used to signal to downstream systems whether or not to sample a particular trace, because we can always drop the current services portion of a trace during Tail Sampling.

Head Sampling can be configured with any standard Open Telemetry `Sampler` or an object with a `ratio` property and optional `acceptRemote` property. The default is the AlwaysOnSampler, which samples every single request.

Examples:

```typescript
const headSampler = new AlwaysOnSampler()
```

```typescript
const headSampler = {
acceptRemote: false //Whether to accept incoming trace contexts
ratio: 0.5 //number between 0 and 1 that represents the ratio of requests to sample. 0 is none and 1 is all requests.
}
```

Tail Sampling on the other hand is done at the end. Because we record every single span, even if it isn't head sampled, it is possible to still sample the local part of a trace in say the event of an error.

Example:

```typescript
const tailSampler = (localTrace: LocalTrace): boolean => {
const localRootSpan = traceInfo.localRootSpan as unknown as ReadableSpan
return localRootSpan.spanContext().traceFlags === TraceFlags.SAMPLED
}
```

The default is a tailSampler that samples traces that have been head sampled or if the local root span is marked as an error.

#### Service

Service identifies the service and version to help with querying.

Example:

```typescript
const service = {
name: 'some_name' //required. The name of your service
version: '1.0.4' //optional: An opaque version string. Can be a semver or git hash for example
namespace: 'namespace' //optional: Useful to group multiple services together in one namespace.
}
```

## Distributed Tracing

One of the advantages of using Open Telemetry is that it makes it easier to do distributed tracing through multiple different services. This library will automatically inject the W3C Trace Context headers when making outbound fetch calls.
One of the advantages of using Open Telemetry is that it makes it easier to do distributed tracing through multiple different services. This library will automatically inject the W3C Trace Context headers when making calls to Durable Objects or outbound fetch calls.

## Limitations

- The worker runtime does not expose accurate timing information to protect against side-channel attacks such as Spectre and will only update the clock on IO, so any CPU heavy processing will look like it takes 0 milliseconds.
- Not everything is auto-instrumented yet. See the lists below for what is and isn't.

Triggers:

- [x] HTTP (`handler.fetch`)
- [x] Queue (`handler.queue`)
- [ ] Cron (`handler.scheduled`)
- [x] Durable Objects
- [x] waitUntil (`ctx.waitUntil`)

Globals/built-ins:

- [x] Fetch
- [x] Caches
- [x] Durable Object Storage

## Sampling
Bindings:

Sampling is currently not supported.
- [x] KV
- [x] Queue
- [x] Durable Objects
- [ ] R2
- [ ] D1
- [ ] Worker Bindings
- [ ] Workers for Platform Dispatch
1 change: 1 addition & 0 deletions examples/queue/.dev.vars
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
otel.headers.x-honeycomb-team=xACRoffXRK3ey8SgmNEJpH
80 changes: 80 additions & 0 deletions examples/queue/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Cloudflare Workers Template

This template makes it easy to build and run [Cloudflare Workers](https://developers.cloudflare.com/workers/), which can be published to the [Cloudflare Global Network](https://www.cloudflare.com/network/), or run directly from Replit using `wrangler dev` (no Cloudflare account required). In the future, `wrangler dev` will be powered by [Workerd](https://github.com/cloudflare/workerd), our Open-Source Workers runtime.

## Setup

### Initialize a Workers project

Click **Run** in your Replit workspace to set up a Workers project with customizable settings using [Wrangler](https://developers.cloudflare.com/workers/wrangler/). By default, it will initialize a Git repository, set up a TypeScript project, and create a Fetch handler.

### Silence Wrangler metrics prompts

Every time a Repl using the Workers Template is booted up, Wrangler will prompt for sending anonymous metrics to Cloudflare. To silence this prompt:

1. Add a [Replit secret](https://docs.replit.com/programming-ide/storing-sensitive-information-environment-variables) with the name `WRANGLER_SEND_METRICS`.
2. Use value `true` to send anonymous metrics to Cloudflare, or `false` to opt-out.

## Develop and run in Replit

After you have initialized your Workers project, select **Run** again to deploy your Worker in dev mode. The **Run** button in your Replit workspace will run your Worker in dev mode, making your project available on a Replit subdomain. After a period of inactivity, your Repl may go to sleep until the **Run** button is pressed or the [Repl receives HTTP traffic](https://docs.replit.com/hosting/deploying-http-servers). To prevent your Repl from sleeping, enable [Always On](https://docs.replit.com/power-ups/always-on) in your Replit workspace settings.

### Develop with persistent data

You can persist development data between sessions. To run your Worker with data persisted in the `data` folder of your Repl, run the following in the Shell tab of your Replit workspace:

```shell
npm run start-persist
```

The **Run** button can also be updated to always run your Worker in persistent mode:
1. Open `package.json`.
2. Update the `replit-run-command` key with a value of `npm run start-persist`.

## Deploy Worker to Cloudflare

To deploy your Worker to the Cloudflare network, you must add your Cloudflare API token and Cloudflare account ID to Replit secrets.

### 1. Add your Cloudflare API token to Replit secrets

To add your Cloudflare API token to Replit secrets:

1. Log in to the [Cloudflare Dashboard](https://dash.cloudflare.com/).
2. In **Account Home**, select **My Profile** on the top right.
3. Select **API Tokens** on the left-hand navigation.
4. Select **Create Token**.
5. Go to **Edit Cloudflare Workers** under **API Token Templates** and select **Use Template**.
6. Under **Account Resources**, select *All accounts* (or a specific account).
7. Under **Zone Resources**, change *Specific zone* to *All zones*.
8. Select **Continue to summary**.
9. Select **Create Token**.
10. This gives you the API token needed. Copy it to [Replit secrets](https://docs.replit.com/programming-ide/storing-sensitive-information-environment-variables) with the name `CLOUDFLARE_API_TOKEN`.

### 2. Add your Cloudflare Account ID to Replit secrets

To add your Cloudflare account ID to Replit secrets:

1. Log in to the Cloudflare dashboard > [**Workers**](https://dash.cloudflare.com/?to=/:account/workers/overview).
2. In **Workers**, find your **Account ID** on the right side of the screen.
3. Select **Click to copy** to copy your Account ID.
4. Add this to [Replit secrets](https://docs.replit.com/programming-ide/storing-sensitive-information-environment-variables) with the name `CLOUDFLARE_ACCOUNT_ID`.

Note: You may have to close and re-open the Shell tab of your Replit workspace before these secrets are available for use.

### Publish Worker to Cloudflare

After adding credentials to Replit secrets, you can publish your Worker to the Cloudflare global network. Your Worker will publish to a `*.workers.dev` subdomain by default. To set up a `*.workers.dev` subdomain, go to the Cloudflare dashboard > [**Workers**](https://dash.cloudflare.com/?to=/:account/workers/overview) > Your subdomain > Change. To publish your project, run:

```shell
npm run deploy
```

After you have deployed your Worker, you can set up a custom domain for your project in the Cloudflare dashboard. To set up a custom domain, go to [**Workers**](https://dash.cloudflare.com/?to=/:account/workers/overview) in the Cloudflare dashboard > select your Worker > **Triggers** > **Add Custom Domain**.

To configure the **Run** button to publish to the Cloudflare global network rather than a Replit subdomain:
1. Open `package.json`.
2. Update the `replit-run-command` key with a value of `npm run deploy`.

## Discord

Join the Cloudflare Developers community Discord to ask questions, show off what you are building, and discuss the platform with other developers: [discord.gg/cloudflaredev](https://discord.gg/cloudflaredev).
Loading