{"id":15715315,"url":"https://github.com/cloudflare/workers-honeycomb-logger","last_synced_at":"2025-04-06T21:16:32.316Z","repository":{"id":42363638,"uuid":"348395417","full_name":"cloudflare/workers-honeycomb-logger","owner":"cloudflare","description":"A library to easily send request events and traces to https://honeycomb.io","archived":false,"fork":false,"pushed_at":"2024-09-27T17:04:53.000Z","size":283,"stargazers_count":77,"open_issues_count":15,"forks_count":18,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-28T00:09:49.339Z","etag":null,"topics":["cloudflare","honeycombio","workers"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudflare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-16T15:18:23.000Z","updated_at":"2025-03-18T03:28:12.000Z","dependencies_parsed_at":"2024-06-18T21:27:54.673Z","dependency_job_id":"5ecfd084-13bf-4c18-bee5-e386ffeb98e2","html_url":"https://github.com/cloudflare/workers-honeycomb-logger","commit_stats":{"total_commits":143,"total_committers":9,"mean_commits":15.88888888888889,"dds":"0.13286713286713292","last_synced_commit":"80a04131f31bc5b6e9c3076b7da1f25db7749b15"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fworkers-honeycomb-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fworkers-honeycomb-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fworkers-honeycomb-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fworkers-honeycomb-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudflare","download_url":"https://codeload.github.com/cloudflare/workers-honeycomb-logger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247550693,"owners_count":20956987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare","honeycombio","workers"],"created_at":"2024-10-03T21:40:54.900Z","updated_at":"2025-04-06T21:16:32.294Z","avatar_url":"https://github.com/cloudflare.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"Honeycomb logger is a simple library that lets you extremely easily export runtime information from your [Cloudflare Workers](https://workers.cloudflare.com/) into [Honeycomb](https://honeycomb.io).\nHoneycomb is an observability platform which allows you to query and graph across any (number of) dimension(s) you have in your data. So you can for example graph request duration for 200 response codes, for GET requests, to a particular URL, for a particular customer.\n\nOr you can drill into an entire trace of a request that errored out, including all subrequests.\n\nTable of Contents\n\n- [Prerequisites](#prerequisites)\n- [Getting Started](#getting-started)\n  - [AddEventListener configuration](#addeventlistener-configuration)\n  - [Module syntax configuration](#module-syntax-configuration)\n  - [Durable Object configuration](#durable-object-configuration)\n- [Config](#config)\n- [Adding logs and other data](#adding-logs-and-other-data)\n- [Traces](#traces)\n- [Dynamic Sampling](#dynamic-sampling)\n- [Cloudflare Pages Support](#cloudflare-pages-support)\n\n### Prerequisites\n\nThis script does not yet work for scheduled workers. It supports Workers in both the `addEventListener` and module syntaxes, including Durable Objects. For more information on Durable Object support, see below.\n\n### Getting started\n\nInstallation is done via the usual `npm install @cloudflare/workers-honeycomb-logger` or `yarn add @cloudflare/workers-honeycomb-logger`.\n\nThe next two things you need are a Honeycomb API key and a dataset name. You can pick any dataset name you like, Honeycomb will automatically create a new dataset if it sees a new name.\n\nThe next step depends on if you are using the `addEventListener` format or the new module format (required for Durable Objects)\n\n⚠️ You also need to enable the `Automatically unpack nested JSON` setting in the dataset settings in https://ui.honeycomb.io to be able to query over all the data that is automatically included.\n\n#### AddEventListener configuration\n\nTo configure the package, you need to wrap your listener with the honeycomb logger. So if your current code looks something like this:\n\n```javascript\naddEventListener('fetch', (event) =\u003e {\n  event.respondWith(handleRequest(event.request))\n})\n\nfunction handleRequest(request) {\n  //your worker code.\n}\n```\n\nYou can change that to:\n\n```javascript\nimport { hc } from '@cloudflare/workers-honeycomb-logger'\n\nconst hc_config = {\n  apiKey: '\u003capi_key\u003e',\n  dataset: '\u003cmy-first-dataset\u003e',\n}\nconst listener = hc(hc_config, (event) =\u003e {\n  event.respondWith(handleRequest(event.request))\n})\n\naddEventListener('fetch', listener)\n\nfunction handleRequest(request) {\n  //your worker code.\n}\n```\n\nYou are now good to go. Read through the config section to see what else you can configure.\nIf you run into any problems, here is a [full example of an addEventListener configured worker](https://github.com/cloudflare/workers-honeycomb-logger/blob/main/run/worker/src/index.js)\n\n#### Module syntax configuration\n\nIf you are using the module syntax, the setup is slightly different. But you still have to wrap the worker.\n\nIf your code was something like this:\n\n```javascript\nexport default {\n  async fetch(request, env, ctx) {\n    return new Response('Hello world!', { status: 200 })\n  },\n}\n```\n\nYou would change that to something like:\n\n```javascript\nconst worker = {\n  async fetch(request, env, ctx) {\n    return new Response('Hello world!', { status: 200 })\n  },\n}\n\nconst config = {\n  apiKey: '__HONEYCOMB_API_KEY__', // can also be provided by setting env var HONEYCOMB_API_KEY\n  dataset: 'my-first-dataset', // can also be provided by setting env var HONEYCOMB_DATASET\n}\n\nexport default wrapModule(config, worker)\n```\n\nYou are now good to go. Read through the config section to see what else you can configure.\nIf you run into any problems, here is a [full example of a module syntax configured worker](https://github.com/cloudflare/workers-honeycomb-logger/blob/main/run/module-worker/src/index.mjs)\n\nIf you don't want to hardcode the API key manually, you can also set the environment variables `HONEYCOMB_API_KEY` and `HONEYCOMB_DATASET` and they will override whatever is inserted into `wrapModule`.\n\n#### Durable Object configuration\n\nIf you are using Durable Objects, we support automatic distributed tracing across both your workers and your Durable Objects.\nYou need to wrap your Worker code with the [module system configuration](#module-syntax-configuration) above, and then wrap your durable object as well.\n\nYou can do it like this:\n\n```javascript\nimport { Counter as counter_do } from './counter.mjs'\n\nconst worker = {\n  async fetch(request, env) {\n    // handleRequest\n  },\n}\n\nconst config = {\n  apiKey: '__HONEYCOMB_API_KEY__', // can also be provided by setting env var HONEYCOMB_API_KEY\n  dataset: 'my-first-dataset', // can also be provided by setting env var HONEYCOMB_DATASET\n}\n\nconst Counter = wrapDurableObject(config, counter_do)\nexport default wrapModule(config, worker)\nexport { Counter }\n```\n\nIf you run into any problems, here is a [full example of a durable object configured worker](https://github.com/cloudflare/workers-honeycomb-logger/blob/main/run/do-worker/src/index.mjs)\n\n### Config\n\nThe config object can take a few extra parameters to add more detail to the events that are sent to Honeycomb or configure other aspects.\n\n```typescript\ninterface Config {\n  apiKey?: string //The honeycomb API Key, can be specified as env var HONEYCOMB_API_KEY\n  dataset?: string //The name of the dataset, can be specified as env var HONEYCOMB_DATASET\n  acceptTraceContext?: boolean //Do you want to accept automatic TraceContext information from clients? Defaults to 'false'\n  data?: any //Any data you want to add to every request. Things like service name, version info etc.\n  redactRequestHeaders?: string[] //Array of headers to redact. Will replace value with `REDACTED`. default is ['authorization', 'cookie', 'referer'].\n  redactResponseHeaders?: string[] //Array of headers to redact. Will replace value with `REDACTED`. default is ['set-cookie'].\n  sampleRates?: SampleRates | SampleRateFn //Either an object or function that configured sampling ([See below](#dynamic-sampling))\n  sendTraceContext?: boolean | RegExp //set this to true to send a TraceContext with all fetch requests. With a Regex, we will check the URL against the regex first. Defaults to 'false'\n  serviceName?: string //The serviceName you want to see in Honeycomb. Defaults to 'worker'\n  debugLog?: boolean // console.log response info for Honeycomb requests. Defaults to false\n}\n```\n\nNOTE: In previous versions there were methods for parsing request and responses, but this becomes an issue when reading the body of the request or the response, so it has been removed. If you want add any information you can do so with the `tracer.addData` method described below.\n\n### Adding logs and other data\n\nIf you want to add any other data or logs to the current request, you can use the `tracer.addData(data: object)` and `tracer.log(message: string)` methods.\nYou can get a reference to the tracer either on the request object, or the second argument in the listener.\n\n```typescript\nasync function handleRequest(request: TracerRequest) {\n  request.tracer.log('handling request')\n  const customer = parseCustomer(request)\n  request.tracer.addData({customer: customer.name})\n  return ...\n}\n```\n\n### Traces\n\nHoneycomb has a concept of a trace, which is a hierarchial representatation of multiple, related events. The Cloudflare Worker Honeycomb logger supports trace events for subrequests (outgoing HTTP fetch requests in your worker) like this:\n\n\u003cimg width=\"1089\" alt=\"Screenshot 2021-03-18 at 10 53 06 AM\" src=\"https://user-images.githubusercontent.com/890386/111732941-ca13d200-88ca-11eb-94cb-a4f30a462788.png\"\u003e\n\nTo be able to associate the a subrequest with the correct incoming request, you will have to use the fetch defined on the tracer described above. The method on the tracer delegates all arguments to the regular fetch method, so the `tracer.fetch` function is a drop-in replacement for all `fetch` function calls.\n\nExample:\n\n```typescript\nasync function handleRequest(request: Request) {\n  return request.tracer.fetch('https://docs.honeycomb.io/api/events/')\n}\n```\n\nIf you want to enable automatic distributed traces from your client to your backend, you can enable the `acceptTrace` property to participate in the trace started by your client and `sendTraceContext` to automatically send through the [TraceContext](https://www.w3.org/TR/trace-context/#examples-of-http-traceparent-headers) to your backend.\nThis only works on the `fetch` methods that are defined on the `tracer` object and is compatible with any of the official Honeycomb beeline frameworks.\nRemember that you do have to use the same `dataset` for all systems to be able to assemble your trace in Honeycomb.\n\n### Dynamic Sampling\n\nOne of the challenges with storing all this information per request is that when you scale that up to past tens of millions of requests as month, it becomes more and more expensive. But at the same time you are almost certainly not very interested in the vast majority of the events. Which is why Honeycomb supports sampling. Sending only a portion of the events there. The problem with doing simple sampling (like sending only 1 in 10 requests for example), is that you lose a lot of events that happen rarely. So Honeycomb and this library support dynamic sampling.\nThe easiest sampling that you can configure is by response code. So you can configure to keep only 1 in 10 responses code 200s, and keep all 5xx.\n\nThe number is technically how many requests it is representative for. An easier way to remember is that a request has a 1/x chance to be sampled.\n\n```typescript\nexport interface SampleRates {\n  '1xx': number\n  '2xx': number\n  '3xx': number\n  '4xx': number\n  '5xx': number\n  exception: number\n}\n```\n\nIn an example:\n\n```typescript\nconst hc_config = {\n  api_key: 'abcd',\n  dataset: 'my-first-dataset',\n  sampleRates: {\n    '1xx': 20,\n    '2xx': 10,\n    '3xx': 5,\n    '4xx': 2,\n    '5xx': 1,\n    exception: 1,\n  },\n}\n```\n\nThis configures the library to only send 1 in 10 requests with a response code in the 200s, but keep all errors; both 500s and exceptions.\n\nIf you want more fine grained control over what is sampled, you can supply a function that takes the entire `data` object of the outer event.\nThis is the exact object that will be sent to Honeycomb, so you can see what values are available there.\nThis includes all information that you have added with `request.tracer.addData()`\n\nPlease note that the `Headers` for both request and response objects are converted into a `Record\u003cstring, string\u003e`. So if you want to check the `content-type` headers in the response, you can do `data.response.headers['content-type']`.\n\nExamples\n\n```typescript\nfunction sampleRates(data: any): number {\n  if (data.request.url.contains('/healthcheck')) {\n    return 0\n  } else if (data.customer.plan === 'enterprise') {\n    return 5\n  } else if (data.response.ok === true) {\n    return 20\n  } else {\n    return 1\n  }\n}\n```\n\nThe one caveat with sampling and distributed tracing is that if you sample in both/all systems independently of one another, that it\nbecomes likely that you will get partial traces.\n\n### Cloudflare Pages support\n\nFor Cloudflare Pages support, check out the [Honeycomb Pages Plugin](https://github.com/cloudflare/pages-plugins/tree/main/packages/honeycomb).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudflare%2Fworkers-honeycomb-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudflare%2Fworkers-honeycomb-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudflare%2Fworkers-honeycomb-logger/lists"}