Skip to content

Commit bcb4d92

Browse files
BridgeARludu12
authored andcommitted
instrumentation: add hono support (#6061)
The instrumentation does not yet handle middlewares, while the basic functionality should work just fine. --------- Co-authored-by: Luke Dunscombe <dunscombe1@gmail.com>
1 parent 68c5e0e commit bcb4d92

File tree

13 files changed

+451
-1
lines changed

13 files changed

+451
-1
lines changed

.github/workflows/apm-integrations.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,14 @@ jobs:
438438
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
439439
- uses: ./.github/actions/plugins/test
440440

441+
hono:
442+
runs-on: ubuntu-latest
443+
env:
444+
PLUGINS: hono
445+
steps:
446+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
447+
- uses: ./.github/actions/plugins/test
448+
441449
http:
442450
strategy:
443451
matrix:

docs/test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ tracer.use('grpc', { client: { metadata: [] } });
339339
tracer.use('grpc', { server: { metadata: [] } });
340340
tracer.use('hapi');
341341
tracer.use('hapi', httpServerOptions);
342+
tracer.use('hono');
343+
tracer.use('hono', httpServerOptions);
342344
tracer.use('http');
343345
tracer.use('http', {
344346
server: httpServerOptions

index.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ interface Plugins {
186186
"graphql": tracer.plugins.graphql;
187187
"grpc": tracer.plugins.grpc;
188188
"hapi": tracer.plugins.hapi;
189+
"hono": tracer.plugins.hono;
189190
"http": tracer.plugins.http;
190191
"http2": tracer.plugins.http2;
191192
"ioredis": tracer.plugins.ioredis;
@@ -1603,6 +1604,12 @@ declare namespace tracer {
16031604
*/
16041605
interface hapi extends HttpServer {}
16051606

1607+
/**
1608+
* This plugin automatically instruments the
1609+
* [hono](https://hono.dev/) module.
1610+
*/
1611+
interface hono extends HttpServer {}
1612+
16061613
/**
16071614
* This plugin automatically instruments the
16081615
* [http](https://nodejs.org/api/http.html) module.

packages/datadog-instrumentations/src/helpers/hooks.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ module.exports = {
5858
grpc: () => require('../grpc'),
5959
handlebars: () => require('../handlebars'),
6060
hapi: () => require('../hapi'),
61+
hono: { esmFirst: true, fn: () => require('../hono') },
6162
http: () => require('../http'),
6263
http2: () => require('../http2'),
6364
https: () => require('../http'),

packages/datadog-instrumentations/src/helpers/register.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ function filename (name, file) {
207207
// This function captures the instrumentation file name for a given package by parsing the hook require
208208
// function given the module name. It is used to ensure that instrumentations such as redis
209209
// that have several different modules being hooked, ie: 'redis' main package, and @redis/client submodule
210-
// return a consistent instrumentation name. This is used later to ensure that atleast some portion of
210+
// return a consistent instrumentation name. This is used later to ensure that at least some portion of
211211
// the integration was successfully instrumented. Prevents incorrect `Found incompatible integration version: ` messages
212212
// Example:
213213
// redis -> "() => require('../redis')" -> redis
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
'use strict'
2+
3+
const shimmer = require('../../datadog-shimmer')
4+
const {
5+
addHook,
6+
channel
7+
} = require('./helpers/instrument')
8+
9+
const routeChannel = channel('apm:hono:request:route')
10+
const handleChannel = channel('apm:hono:request:handle')
11+
const errorChannel = channel('apm:hono:request:error')
12+
13+
function wrapFetch (fetch) {
14+
return function (request, env, executionCtx) {
15+
handleChannel.publish({ req: env.incoming })
16+
return fetch.apply(this, arguments)
17+
}
18+
}
19+
20+
function wrapCompose (compose) {
21+
return function (middleware, onError, onNotFound) {
22+
const instrumentedOnError = (...args) => {
23+
const [error, context] = args
24+
const req = context.env.incoming
25+
errorChannel.publish({ req, error })
26+
return onError(...args)
27+
}
28+
29+
const instrumentedMiddlewares = middleware.map(h => {
30+
const [[fn, meta], params] = h
31+
32+
// TODO: handle middleware instrumentation
33+
const instrumentedFn = (...args) => {
34+
const context = args[0]
35+
const req = context.env.incoming
36+
const route = meta.path
37+
routeChannel.publish({
38+
req,
39+
route
40+
})
41+
return fn(...args)
42+
}
43+
return [[instrumentedFn, meta], params]
44+
})
45+
return compose.apply(this, [instrumentedMiddlewares, instrumentedOnError, onNotFound])
46+
}
47+
}
48+
49+
addHook({
50+
name: 'hono',
51+
versions: ['>=4'],
52+
file: 'dist/hono.js'
53+
}, hono => {
54+
class Hono extends hono.Hono {
55+
constructor (...args) {
56+
super(...args)
57+
shimmer.wrap(this, 'fetch', wrapFetch)
58+
}
59+
}
60+
61+
hono.Hono = Hono
62+
63+
return hono
64+
})
65+
66+
addHook({
67+
name: 'hono',
68+
versions: ['>=4'],
69+
file: 'dist/cjs/hono.js'
70+
}, hono => {
71+
class Hono extends hono.Hono {
72+
constructor (...args) {
73+
super(...args)
74+
shimmer.wrap(this, 'fetch', wrapFetch)
75+
}
76+
}
77+
78+
return Object.create(hono, {
79+
Hono: {
80+
get () {
81+
return Hono
82+
},
83+
enumerable: true,
84+
}
85+
})
86+
})
87+
88+
addHook({
89+
name: 'hono',
90+
versions: ['>=4'],
91+
file: 'dist/cjs/compose.js'
92+
}, Compose => {
93+
return shimmer.wrap(Compose, 'compose', wrapCompose, { replaceGetter: true })
94+
})
95+
96+
addHook({
97+
name: 'hono',
98+
versions: ['>=4'],
99+
file: 'dist/compose.js'
100+
}, Compose => {
101+
return shimmer.wrap(Compose, 'compose', wrapCompose)
102+
})
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict'
2+
3+
const RouterPlugin = require('../../datadog-plugin-router/src')
4+
const web = require('../../dd-trace/src/plugins/util/web')
5+
6+
class HonoPlugin extends RouterPlugin {
7+
static get id () {
8+
return 'hono'
9+
}
10+
11+
constructor (...args) {
12+
super(...args)
13+
14+
this.addSub('apm:hono:request:handle', ({ req }) => {
15+
this.setFramework(req, 'hono', this.config)
16+
})
17+
18+
this.addSub('apm:hono:request:route', ({ req, route }) => {
19+
web.setRoute(req, route)
20+
})
21+
22+
this.addSub('apm:hono:request:error', ({ req, error }) => {
23+
web.addError(req, error)
24+
})
25+
}
26+
}
27+
28+
module.exports = HonoPlugin

0 commit comments

Comments
 (0)