How to add Honeycomb to a Remix.run app on Cloudflare Workers
With a new paradigm of cloudflare workers and other functions at the edge, and their alluring promise of no cold starts and great performance, one thing we especially want to keep is observability.
Who doesn't want to see those low low numbers in a pretty graph? Knowing what our systems are doing remains evergreen in value. So using honeycomb is a pretty sensible choice.
So how does telemetry translate to this new world?
Key Takeaways
- How to get the most basic shape of data from a Cloudflare Worker into honeycomb
- Basic steps to instrumenting a Remix app
Adding Honeycomb to Cloudflare Workers
This is focused on a remix.run application, so we'll assume that you have already got a Remix app targeting the Workers deployment strategy.
You'll need to install the cloudflare package:
npm install @cloudflare/workers-honeycomb-logger
Then your worker/index.js
needs updating to look like:
import {
createEventHandler,
} from "@remix-run/cloudflare-workers";
import {
wrapEventListener,
} from '@cloudflare/workers-honeycomb-logger'
import * as build from "../build";
const hc_config = {
apiKey: HONEYCOMB_API_KEY,
dataset: 'test-dataset',
}
addEventListener("fetch",
wrapEventListener(
hc_config,
createEventHandler({
build,
// Puts the tracer into your Remix `context`
getLoadContext: (event) => {
return {
tracer: event.request.tracer
}
}
})
),
);
That's it... you're getting data into honeycomb. Well, except you're probably not seeing it appear just yet outside of the raw data.
Getting raw data to traces
You've got data coming into a dataset, but it's really just raw JSON and honeycomb isn't converting it to traces. So, once you've got a dataset in Honeycomb:
- Go to
Datasets
on the admin page - Go to
Settings
for your dataset - In the dataset's settings access the
Schema
tab - Turn on
automatically unpack nested json
and set a depth of 2
That alone should start getting you traces.
You might also want to take a look at the Definitions
tab, and do
some mapping between the raw input and what you want honeycomb to use.
Instrumenting the Remix app code
So you'll have noticed in the worker/index.js
that we have added a getLoadContext
function
which receives the original FetchEvent
. Thanks to the wrapEventListener
that fetch event now has
the tracer attached to the request, so we pass it along into remix.
This means that in your app code, you can access the tracer. For example, in an action function you can pull in the context, which has the tracer on it.
export const action: ActionFunction = async ({ request, context }) => {
const authSpan = context.tracer.startChildSpan('authorize');
const authorizeResult = await authorize(request);
authSpan.finish();
// other code
}
Making fetch (traces) happen
(Unoriginal, but who doesn't love a Mean Girls quote...)
Automatic tracing of fetches doesn't come for free, but the tracer utility provides a fetch
function that wraps
native fetch. So using the context.tracer.fetch
will give you wrapped fetch calls pretty easily.
This came in handy for tracing fauna database calls in a pretty trivial way. You can
of course put in manual spans before and after calls, but thankfully the faunadb Client
accepts a fetch
parameter, so you can just pass in the tracer's wrapped fetch.
const faunaClient = new faunadb.Client({
domain: FAUNA_DB_DOMAIN,
secret: accessToken,
fetch: (url, init) => context.tracer.fetch(url, init)
});
Marvel at your beautiful fetches coming through!
Wrap-up
I had originally had this article comment on the limited insights - thinking they were limited to the top level request.
Humble thanks to Liz Fong-Jones pointing me in the direction of the original cloudflare honeycomb logger library author, Erwin var der Koogh, I was prompted to dig in further.
So the picture is much better than I'd originally thought on first pass, we can get those beautiful insights still.
Maybe not as easily as a native node.js
environment and
automatic instrumentation, but this might also be something I just
need to spend more time on learning!
Looking forward to seeing how to instrument the frontend of a remix app with Honeycomb next, too!