|
| 1 | +# Pydantic Logfire — Uncomplicated Observability — JavaScript SDK |
| 2 | + |
| 3 | +From the team behind [Pydantic](https://pydantic.dev/), **Logfire** is an observability platform built on the same belief as our |
| 4 | +open source library — that the most powerful tools can be easy to use. |
| 5 | + |
| 6 | +What sets Logfire apart: |
| 7 | + |
| 8 | +- **Simple and Powerful:** Logfire's dashboard is simple relative to the power it provides, ensuring your entire engineering team will actually use it. |
| 9 | +- **SQL:** Query your data using standard SQL — all the control and (for many) nothing new to learn. Using SQL also means you can query your data with existing BI tools and database querying libraries. |
| 10 | +- **OpenTelemetry:** Logfire is an opinionated wrapper around OpenTelemetry, allowing you to leverage existing tooling, infrastructure, and instrumentation for many common packages, and enabling support for virtually any language. We offer full support for all OpenTelemetry signals (traces, metrics and logs). |
| 11 | + |
| 12 | +**Feel free to report issues and ask any questions about Logfire in this repository!** |
| 13 | + |
| 14 | +This repo contains the JavaScript SDK for `logfire` and its documentation; the server application for recording and displaying data is closed source. |
| 15 | + |
| 16 | + |
| 17 | +## Usage |
| 18 | + |
| 19 | +Depending on your environment, you can integrate Logfire in several ways. Follow the specific instructions below: |
| 20 | + |
| 21 | +### Cloudflare Workers |
| 22 | + |
| 23 | +First, install the `@microlabs/otel-cf-workers` [NPM package](https://github.com/evanderkoogh/otel-cf-workers) and the `@pydantic/logfire-cf-workers @pydantic/logfire-api` NPM package: |
| 24 | + |
| 25 | +```sh |
| 26 | +npm install @microlabs/otel-cf-workers @opentelemetry/api @pydantic/logfire-cf-workers @pydantic/logfire-api |
| 27 | +``` |
| 28 | +As per the otel-cf-workers package instructions, add `compatibility_flags = [ "nodejs_compat" ]` to your wrangler.toml or `"compatibility_flags": ["nodejs_compat"]` if you're using `wrangler.jsonc`. |
| 29 | + |
| 30 | +Add your [Logfire write token](https://logfire.pydantic.dev/docs/how-to-guides/create-write-tokens/) to your Wrangler file: |
| 31 | + |
| 32 | +`wrangler.jsonc`: |
| 33 | + |
| 34 | +```json |
| 35 | + "vars": { |
| 36 | + "LOGFIRE_TOKEN": "your-write-token", |
| 37 | + }, |
| 38 | +``` |
| 39 | + |
| 40 | +`wrangler.toml`: |
| 41 | + |
| 42 | +```toml |
| 43 | +[vars] |
| 44 | +LOGFIRE_WRITE_TOKEN="your-write-token" |
| 45 | +``` |
| 46 | + |
| 47 | +Next, add the necessary instrumentation around your handler. The `tracerConfig` function will extract your write token from the `env` object and provide the necessary configuration for the instrumentation: |
| 48 | + |
| 49 | +```ts |
| 50 | +import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers'; |
| 51 | +import { tracerConfig } from '@pydantic/logfire-cf-workers'; |
| 52 | +// Optional, if you want to manually create spans. Regular OTel API can be used as well. |
| 53 | +import * as logfire from '@pydantic/logfire-api'; |
| 54 | + |
| 55 | +export interface Env { |
| 56 | + LOGFIRE_TOKEN: string; |
| 57 | + LOGFIRE_BASE_URL: string; |
| 58 | + OTEL_TEST: KVNamespace; |
| 59 | +} |
| 60 | + |
| 61 | +const handler = { |
| 62 | + async fetch(): Promise<Response> { |
| 63 | + logfire.info('Logfire: info from inside the worker body'); |
| 64 | + return new Response('Hello World!'); |
| 65 | + }, |
| 66 | +} satisfies ExportedHandler<Env>; |
| 67 | + |
| 68 | +const config: ResolveConfigFn = (env: Env, _trigger) => { |
| 69 | + return { |
| 70 | + service: { name: 'cloudflare-worker', namespace: '', version: '1.0.0' }, |
| 71 | + ...tracerConfig(env), |
| 72 | + }; |
| 73 | +}; |
| 74 | + |
| 75 | +export default instrument(handler, config); |
| 76 | +``` |
| 77 | + |
| 78 | +A working example can be found in the `examples/cloudflare-worker` directory. |
| 79 | + |
| 80 | +### Next.js / Vercel |
| 81 | + |
| 82 | +Vercel provides a comprehensive OpenTelemetry integration through the `@vercel/otel` package. After following [their integration instructions](https://vercel.com/docs/otel), Add the following two env variables to your project: |
| 83 | + |
| 84 | +```sh |
| 85 | +OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://logfire-api.pydantic.dev/v1/traces |
| 86 | +OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://logfire-api.pydantic.dev/v1/metrics |
| 87 | +OTEL_EXPORTER_OTLP_HEADERS='Authorization=your-write-token' |
| 88 | +``` |
| 89 | + |
| 90 | +The above will point the instrumentation to Logfire. |
| 91 | + |
| 92 | +Optionally, you can use the Logfire API package for creating manual spans. Install the `@pydantic/logfire-api` NPM package and call the respective methods from your server-side code: |
| 93 | + |
| 94 | +```tsx |
| 95 | +import * as logfire from '@pydantic/logfire-api' |
| 96 | + |
| 97 | +export default async function Home() { |
| 98 | + return logfire.startActiveSpan(logfire.Level.Warning, 'A warning span', {}, {}, async () => { |
| 99 | + logfire.info('Nested info span'); |
| 100 | + return <div>Hello</div>; |
| 101 | + }) |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +A working example can be found in the `examples/nextjs` directory. |
| 106 | + |
| 107 | +### Express, generic Node instrumentation |
| 108 | + |
| 109 | +For the purposes of the example, we will instrument this simple Express app: |
| 110 | + |
| 111 | +```ts |
| 112 | +/*app.ts*/ |
| 113 | +import express, type { Express } from 'express'; |
| 114 | + |
| 115 | +const PORT: number = parseInt(process.env.PORT || '8080'); |
| 116 | +const app: Express = express(); |
| 117 | + |
| 118 | +function getRandomNumber(min: number, max: number) { |
| 119 | + return Math.floor(Math.random() * (max - min + 1) + min); |
| 120 | +} |
| 121 | + |
| 122 | +app.get('/rolldice', (req, res) => { |
| 123 | + res.send(getRandomNumber(1, 6).toString()); |
| 124 | +}); |
| 125 | + |
| 126 | +app.listen(PORT, () => { |
| 127 | + console.log(`Listening for requests on http://localhost:${PORT}`); |
| 128 | +}); |
| 129 | +``` |
| 130 | + |
| 131 | +Next, we will install the `logfire` and `dotenv` NPM packages, so that we can keep our Logfire write token in a `.env` file: |
| 132 | + |
| 133 | +```sh |
| 134 | +npm install logfire dotenv |
| 135 | +``` |
| 136 | + |
| 137 | +Add your token to the `.env` file: |
| 138 | + |
| 139 | + |
| 140 | +```sh |
| 141 | +LOGFIRE_TOKEN=your-write-token |
| 142 | +``` |
| 143 | + |
| 144 | +Afterwards, we will create an `instrumentation.ts` file that will set up the instrumentation. The `logfire` package includes a `configure` function that simplifies the setup: |
| 145 | + |
| 146 | +```ts |
| 147 | +// instrumentation.ts |
| 148 | +import * as logfire from 'logfire' |
| 149 | +import 'dotenv/config' |
| 150 | + |
| 151 | +logfire.configure() |
| 152 | +``` |
| 153 | + |
| 154 | +The `logfire.configure` call should happen before the actual express module imports, so your NPM start script should look something like this (`package.json`): |
| 155 | + |
| 156 | +```json |
| 157 | + "scripts": { |
| 158 | + "start": "npx ts-node --require ./instrumentation.ts app.ts" |
| 159 | + }, |
| 160 | +``` |
| 161 | + |
| 162 | +#### Configuring the instrumentation |
| 163 | + |
| 164 | +The `logfire.configure` function accepts a set of configuration options that control the behavior of the instrumentation. Alternatively, you can [use environment variables](https://logfire.pydantic.dev/docs/reference/configuration/#programmatically-via-configure) to configure the instrumentation. |
| 165 | + |
| 166 | +## Trace API |
| 167 | + |
| 168 | +The `@pydantic/logfire-api` exports several convenience wrappers around the OpenTelemetry span creation API. The `logfire` package re-exports those. |
| 169 | + |
| 170 | +The following methods create spans with the respective log levels (ordered by severity): |
| 171 | + |
| 172 | +* `logfire.trace` |
| 173 | +* `logfire.debug` |
| 174 | +* `logfire.info` |
| 175 | +* `logfire.notice` |
| 176 | +* `logfire.warn` |
| 177 | +* `logfire.error` |
| 178 | +* `logfire.fatal` |
| 179 | + |
| 180 | +Each method accepts a message, attributes, and, optionally options that let you specify the span tags. The attributes values must be serializable to JSON. |
| 181 | + |
| 182 | +```ts |
| 183 | +function info(message: string, attributes?: Record<string, unknown>, options?: LogOptions): void |
| 184 | +``` |
| 185 | + |
| 186 | +## Contributing |
| 187 | + |
| 188 | +See [CONTRIBUTING.md](CONTRIBUTING.md) for development instructions. |
| 189 | + |
| 190 | +## License |
| 191 | + |
| 192 | +MIT |
0 commit comments