Skip to content

Commit 2d82fb1

Browse files
committed
feat: start adding support to cf pages
1 parent d0e5e58 commit 2d82fb1

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@microlabs/otel-cf-workers",
3-
"version": "1.0.0-rc.24",
3+
"version": "1.0.0-rc.25",
44
"main": "dist/cjs/index.js",
55
"module": "dist/esm/index.js",
66
"types": "dist/esm/index.d.ts",
@@ -24,7 +24,7 @@
2424
"fix-dist": "echo '{\"type\": \"module\"}' > dist/esm/package.json && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json",
2525
"build": "run-s -l clean build-esm build-cjs fix-dist",
2626
"release": "run-s build publish",
27-
"publish": "changeset publish",
27+
"publish": "pnpm build",
2828
"preversion": "run-s -l check:* build",
2929
"prepublishOnly": "run-s -l check:* build",
3030
"check": "run-s -l check:*",

src/instrumentation/fetch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export function getParentContextFromHeaders(headers: Headers): Context {
110110
})
111111
}
112112

113-
function getParentContextFromRequest(request: Request) {
113+
export function getParentContextFromRequest(request: Request) {
114114
const workerConfig = getActiveConfig()
115115
const acceptTraceContext =
116116
typeof workerConfig.handlers.fetch.acceptTraceContext === 'function'

src/instrumentation/page.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { ReadableSpan } from '@opentelemetry/sdk-trace-base'
2+
import { Initialiser, setConfig } from '../config'
3+
import { exportSpans, proxyExecutionContext } from './common'
4+
// import { instrumentEnv } from "./env"
5+
import { Exception, SpanKind, SpanOptions, SpanStatusCode, context as api_context, trace } from '@opentelemetry/api'
6+
import { wrap } from '../wrap'
7+
import {
8+
gatherIncomingCfAttributes,
9+
gatherRequestAttributes,
10+
gatherResponseAttributes,
11+
getParentContextFromRequest,
12+
} from './fetch'
13+
14+
type PageHandlerArgs = Parameters<PagesFunction>
15+
16+
let cold_start = true
17+
export function executePageHandler(pagesFn: PagesFunction, [request]: PageHandlerArgs): Promise<Response> {
18+
const spanContext = getParentContextFromRequest(request.request)
19+
20+
const tracer = trace.getTracer('pagesHandler')
21+
const attributes = {
22+
['faas.trigger']: 'http',
23+
['faas.coldstart']: cold_start,
24+
['faas.invocation_id']: request.request.headers.get('cf-ray') ?? undefined,
25+
}
26+
cold_start = false
27+
Object.assign(attributes, gatherRequestAttributes(request.request))
28+
Object.assign(attributes, gatherIncomingCfAttributes(request.request))
29+
const options: SpanOptions = {
30+
attributes,
31+
kind: SpanKind.SERVER,
32+
}
33+
34+
console.log(request.data)
35+
36+
const promise = tracer.startActiveSpan(
37+
`${request.request.method} ${request.functionPath}`,
38+
options,
39+
spanContext,
40+
async (span) => {
41+
const readable = span as unknown as ReadableSpan
42+
try {
43+
const response: Response = await pagesFn(request)
44+
span.setAttributes(gatherResponseAttributes(response))
45+
if (readable.attributes['http.route']) {
46+
span.updateName(`${request.request.method} ${readable.attributes['http.route']}`)
47+
}
48+
span.end()
49+
50+
return response
51+
} catch (error) {
52+
if (readable.attributes['http.route']) {
53+
span.updateName(`${request.request.method} ${readable.attributes['http.route']}`)
54+
}
55+
span.recordException(error as Exception)
56+
span.setStatus({ code: SpanStatusCode.ERROR })
57+
span.end()
58+
throw error
59+
}
60+
},
61+
)
62+
return promise
63+
}
64+
65+
export function createPageHandler<
66+
E = unknown,
67+
P extends string = any,
68+
D extends Record<string, unknown> = Record<string, unknown>,
69+
>(pageFn: PagesFunction<E, P, D>, initialiser: Initialiser): PagesFunction<E, P, D> {
70+
const pagesHandler: ProxyHandler<PagesFunction> = {
71+
apply: async (target, _thisArg, argArray: Parameters<PagesFunction>): Promise<Response> => {
72+
const [orig_ctx] = argArray
73+
const config = initialiser(orig_ctx.env as Record<string, unknown>, orig_ctx.request)
74+
// const env = instrumentEnv(orig_ctx.env as Record<string, unknown>)
75+
const { ctx, tracker } = proxyExecutionContext(orig_ctx)
76+
const context = setConfig(config)
77+
78+
try {
79+
const args: PageHandlerArgs = [ctx] as PageHandlerArgs
80+
return await api_context.with(context, executePageHandler, undefined, target, args)
81+
} catch (error) {
82+
throw error
83+
} finally {
84+
orig_ctx.waitUntil(exportSpans(tracker))
85+
}
86+
},
87+
}
88+
return wrap(pageFn, pagesHandler)
89+
}

src/sdk.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { instrumentGlobalCache } from './instrumentation/cache.js'
2929
import { createQueueHandler } from './instrumentation/queue.js'
3030
import { DOClass, instrumentDOClass } from './instrumentation/do.js'
3131
import { createScheduledHandler } from './instrumentation/scheduled.js'
32+
import { createPageHandler } from './instrumentation/page.js'
3233

3334
type FetchHandler = ExportedHandlerFetchHandler<unknown, unknown>
3435
type ScheduledHandler = ExportedHandlerScheduledHandler<unknown>
@@ -142,7 +143,7 @@ function parseConfig(supplied: TraceConfig): ResolvedTraceConfig {
142143
}
143144
}
144145

145-
function createInitialiser(config: ConfigurationOption): Initialiser {
146+
export function createInitialiser(config: ConfigurationOption): Initialiser {
146147
if (typeof config === 'function') {
147148
return (env, trigger) => {
148149
const conf = parseConfig(config(env, trigger))
@@ -158,6 +159,18 @@ function createInitialiser(config: ConfigurationOption): Initialiser {
158159
}
159160
}
160161

162+
export function instrumentPage<
163+
E = unknown,
164+
P extends string = any,
165+
D extends Record<string, unknown> = Record<string, unknown>,
166+
>(handler: PagesFunction<E, P, D>, config: ConfigurationOption): PagesFunction<E, P, D> {
167+
const initialiser = createInitialiser(config)
168+
169+
handler = createPageHandler(handler, initialiser)
170+
171+
return handler
172+
}
173+
161174
export function instrument<E, Q, C>(
162175
handler: ExportedHandler<E, Q, C>,
163176
config: ConfigurationOption,

0 commit comments

Comments
 (0)