autotel-adapters 0.3.9 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/skills/autotel-adapters/SKILL.md +209 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autotel-adapters",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"description": "Framework adapters and composable DX helpers for autotel",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -57,10 +57,11 @@
|
|
|
57
57
|
"files": [
|
|
58
58
|
"dist",
|
|
59
59
|
"src",
|
|
60
|
-
"README.md"
|
|
60
|
+
"README.md",
|
|
61
|
+
"skills"
|
|
61
62
|
],
|
|
62
63
|
"dependencies": {
|
|
63
|
-
"autotel": "
|
|
64
|
+
"autotel": "4.0.0"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"hono": ">=4.12.23",
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: autotel-adapters
|
|
3
|
+
description: >
|
|
4
|
+
Framework adapters for autotel that add request-scoped logging, tracing, and utility helpers for Next.js, Nitro, Cloudflare Workers, Hono, and TanStack Start.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# autotel-adapters
|
|
8
|
+
|
|
9
|
+
Framework-specific wrappers around autotel's core tracing primitives. Each adapter provides:
|
|
10
|
+
|
|
11
|
+
- A handler wrapper that opens a span and binds a request-scoped `RequestLogger`
|
|
12
|
+
- A `useLogger()` function that retrieves the logger from within the handler
|
|
13
|
+
- A toolkit object (`*Toolkit`) bundling `useLogger`, `parseError`, `createStructuredError`, and `createDrainPipeline`
|
|
14
|
+
|
|
15
|
+
All adapters use `AsyncLocalStorage` (or a `WeakMap` for Cloudflare) internally so logger access is implicit — you never pass a logger through call chains manually.
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
Install the package and the relevant peer dependency for your framework:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add autotel-adapters autotel
|
|
23
|
+
# peer deps (install only the ones you use)
|
|
24
|
+
pnpm add next # Next.js
|
|
25
|
+
pnpm add nitropack h3 # Nitro
|
|
26
|
+
pnpm add hono # Hono
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Configuration / Core Patterns
|
|
30
|
+
|
|
31
|
+
### Next.js
|
|
32
|
+
|
|
33
|
+
Import from the subpath `autotel-adapters/next` (or from the barrel `autotel-adapters`).
|
|
34
|
+
|
|
35
|
+
**Option A — per-handler wrap:**
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { withAutotel, useLogger } from 'autotel-adapters/next';
|
|
39
|
+
|
|
40
|
+
export const GET = withAutotel(async (request) => {
|
|
41
|
+
const log = useLogger(request);
|
|
42
|
+
log.info('handling GET');
|
|
43
|
+
return Response.json({ ok: true });
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Option B — create a shared adapter with defaults:**
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// lib/autotel.ts
|
|
51
|
+
import { createNextAdapter } from 'autotel-adapters/next';
|
|
52
|
+
|
|
53
|
+
export const { withAutotel, useLogger, parseError } = createNextAdapter({
|
|
54
|
+
spanName: (req) => `api ${new URL(req?.url ?? '/').pathname}`,
|
|
55
|
+
enrich: (req) => ({ 'tenant.id': req?.headers?.get('x-tenant-id') }),
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`withAutotel` accepts any function whose first argument is `NextRequestLike`. The `spanName` option can be a static string or a function receiving the request. The auto-enrichment sets `http.request.method`, `url.full`, `http.route`, and `http.request.header.x-request-id`.
|
|
60
|
+
|
|
61
|
+
### Nitro
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { withAutotelEventHandler, useLogger } from 'autotel-adapters/nitro';
|
|
65
|
+
import { defineEventHandler } from 'h3';
|
|
66
|
+
|
|
67
|
+
export default defineEventHandler(
|
|
68
|
+
withAutotelEventHandler(async (event) => {
|
|
69
|
+
const log = useLogger(event);
|
|
70
|
+
log.info('handling event');
|
|
71
|
+
return { ok: true };
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`withAutotelEventHandler` reads `event.method`, `event.path`, and `event.context.requestId` automatically. Use `createNitroAdapter` to share options across handlers.
|
|
77
|
+
|
|
78
|
+
### Cloudflare Workers
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { withAutotelFetch, useLogger } from 'autotel-adapters/cloudflare';
|
|
82
|
+
|
|
83
|
+
export default {
|
|
84
|
+
fetch: withAutotelFetch(async (request, env, ctx) => {
|
|
85
|
+
const log = useLogger(request);
|
|
86
|
+
log.info('handling fetch');
|
|
87
|
+
return new Response('ok');
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Cloudflare stores the logger in a `WeakMap` keyed on the request object (no `AsyncLocalStorage` available in Workers). Auto-enrichment also reads `cf.country`, `cf.colo`, and `cf.city`. The `enrich` callback receives `(request, env, ctx)` for access to environment bindings.
|
|
93
|
+
|
|
94
|
+
### Hono
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { Hono } from 'hono';
|
|
98
|
+
import { honoToolkit } from 'autotel-adapters/hono';
|
|
99
|
+
|
|
100
|
+
const app = new Hono();
|
|
101
|
+
|
|
102
|
+
app.get('/', (c) => {
|
|
103
|
+
const log = honoToolkit.useLogger(c);
|
|
104
|
+
log.info('hello hono');
|
|
105
|
+
return c.json({ ok: true });
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`honoToolkit` is a pre-built `AdapterToolkit<Context>`. There is no handler wrapper for Hono — use autotel's `trace()` directly if you need a span.
|
|
110
|
+
|
|
111
|
+
### TanStack Start
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { tanstackToolkit } from 'autotel-adapters/tanstack';
|
|
115
|
+
|
|
116
|
+
// Inside a server function or API route:
|
|
117
|
+
const log = tanstackToolkit.useLogger({ pathname: '/api/data', method: 'GET' });
|
|
118
|
+
log.info('handling request');
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### AdapterToolkit interface
|
|
122
|
+
|
|
123
|
+
Every toolkit (and `createNextAdapter`/`createNitroAdapter`/`createCloudflareAdapter`) exposes:
|
|
124
|
+
|
|
125
|
+
| Member | Description |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `useLogger(ctx?, opts?)` | Get the request-scoped `RequestLogger` |
|
|
128
|
+
| `parseError(error)` | Normalise any thrown value into `ParsedError` |
|
|
129
|
+
| `createStructuredError(input)` | Build a `StructuredError` for consistent API error shapes |
|
|
130
|
+
| `createDrainPipeline(opts?)` | Create a batching drain pipeline |
|
|
131
|
+
|
|
132
|
+
### Custom adapter (createAdapterToolkit)
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { createAdapterToolkit } from 'autotel-adapters/core';
|
|
136
|
+
|
|
137
|
+
const myToolkit = createAdapterToolkit<MyContext>({
|
|
138
|
+
adapterName: 'my-framework',
|
|
139
|
+
enrich: (ctx) => ({ 'tenant.id': ctx.tenantId }),
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Common Mistakes
|
|
144
|
+
|
|
145
|
+
### HIGH — Calling useLogger outside a traced handler
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// WRONG: no active trace context
|
|
149
|
+
export async function myFunction() {
|
|
150
|
+
const log = useLogger(); // throws: "No active trace context"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// CORRECT: always call useLogger inside a handler wrapped with withAutotel / withAutotelEventHandler
|
|
156
|
+
export const GET = withAutotel(async (request) => {
|
|
157
|
+
const log = useLogger(request); // ok — trace context is active
|
|
158
|
+
await myFunction(log); // pass the logger down if needed
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`useLogger` looks up an `AsyncLocalStorage` store populated by the handler wrapper. Calling it outside that wrapper throws.
|
|
163
|
+
|
|
164
|
+
### HIGH — Importing from wrong subpath
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// WRONG
|
|
168
|
+
import { honoToolkit } from 'autotel-adapters'; // barrel re-exports do exist, but...
|
|
169
|
+
import { useLogger } from 'autotel-adapters'; // this is the Next.js useLogger, not Hono's
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// CORRECT: use framework-specific subpaths
|
|
174
|
+
import { honoToolkit } from 'autotel-adapters/hono';
|
|
175
|
+
import { useLogger } from 'autotel-adapters/next';
|
|
176
|
+
import { withAutotelEventHandler } from 'autotel-adapters/nitro';
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### MEDIUM — Skipping the request argument in Next.js useLogger
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// WRONG: loses auto-enrichment (method, url, route, requestId)
|
|
183
|
+
const log = useLogger();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// CORRECT: pass the request so auto-enrichment runs
|
|
188
|
+
const log = useLogger(request);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The request argument is optional only when you are certain the `AsyncLocalStorage` store is already populated (i.e., called from code deeply nested inside a `withAutotel`-wrapped handler).
|
|
192
|
+
|
|
193
|
+
### MEDIUM — Using createCloudflareAdapter without passing request to useLogger
|
|
194
|
+
|
|
195
|
+
In Cloudflare Workers, the logger is stored per-request in a `WeakMap`. If you call `useLogger()` without the request object, you always get a new logger with no stored enrichment.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// WRONG
|
|
199
|
+
const log = useLogger(); // new logger, not the one from withAutotelFetch
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// CORRECT
|
|
204
|
+
const log = useLogger(request); // retrieves from WeakMap
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Version
|
|
208
|
+
|
|
209
|
+
Targets autotel-adapters v0.2.4. Peer frameworks: Next.js >=16.2.1, Hono >=4.12.9, Nitro/h3 ^2.0.0. See also: `autotel` (core), `autotel-backends` (vendor configs).
|