Skip to content

Commit aa391f9

Browse files
committed
add middleware enter/exit/finish instrumentations to hono
1 parent f42c608 commit aa391f9

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
'use strict'
2+
3+
const axios = require('axios')
4+
const { expect } = require('chai')
5+
const dc = require('dc-polyfill')
6+
const { describe, it, beforeEach, before, after } = require('mocha')
7+
const sinon = require('sinon')
8+
9+
const agent = require('../../dd-trace/test/plugins/agent')
10+
const { withVersions } = require('../../dd-trace/test/setup/mocha')
11+
12+
withVersions('hono', 'hono', version => {
13+
describe('hono instrumentation', () => {
14+
let routeChannelCb, handleChannelCb, errorChannelCb, nextChannelCb
15+
let enterChannelCb, exitChannelCb, finishChannelCb
16+
let port, server, middlewareCalled
17+
18+
const routeChannel = dc.channel('apm:hono:request:route')
19+
const handleChannel = dc.channel('apm:hono:request:handle')
20+
const errorChannel = dc.channel('apm:hono:request:error')
21+
const nextChannel = dc.channel('apm:hono:middleware:next')
22+
const enterChannel = dc.channel('apm:hono:middleware:enter')
23+
const exitChannel = dc.channel('apm:hono:middleware:exit')
24+
const finishChannel = dc.channel('apm:hono:middleware:finish')
25+
26+
before(() => {
27+
return agent.load('hono', { client: false })
28+
})
29+
30+
before((done) => {
31+
const { Hono } = require(`../../../versions/hono@${version}`).get()
32+
const { serve } = require('../../../versions/@hono/node-server').get()
33+
const app = new Hono()
34+
35+
// Add a middleware
36+
app.use(async (_c, next) => {
37+
middlewareCalled()
38+
await next()
39+
})
40+
41+
// Add a route
42+
app.get('/test', (c) => {
43+
return c.text('OK')
44+
})
45+
46+
// Add an error route
47+
app.get('/error', (_c) => {
48+
throw new Error('test error')
49+
})
50+
51+
server = serve({ port: 0, fetch: app.fetch }, (info) => {
52+
port = info.port
53+
done()
54+
})
55+
})
56+
57+
beforeEach(() => {
58+
routeChannelCb = sinon.stub()
59+
handleChannelCb = sinon.stub()
60+
errorChannelCb = sinon.stub()
61+
nextChannelCb = sinon.stub()
62+
enterChannelCb = sinon.stub()
63+
exitChannelCb = sinon.stub()
64+
finishChannelCb = sinon.stub()
65+
middlewareCalled = sinon.stub()
66+
67+
routeChannel.subscribe(routeChannelCb)
68+
handleChannel.subscribe(handleChannelCb)
69+
errorChannel.subscribe(errorChannelCb)
70+
nextChannel.subscribe(nextChannelCb)
71+
enterChannel.subscribe(enterChannelCb)
72+
exitChannel.subscribe(exitChannelCb)
73+
finishChannel.subscribe(finishChannelCb)
74+
})
75+
76+
afterEach(() => {
77+
routeChannel.unsubscribe(routeChannelCb)
78+
handleChannel.unsubscribe(handleChannelCb)
79+
errorChannel.unsubscribe(errorChannelCb)
80+
nextChannel.unsubscribe(nextChannelCb)
81+
enterChannel.unsubscribe(enterChannelCb)
82+
exitChannel.unsubscribe(exitChannelCb)
83+
finishChannel.unsubscribe(finishChannelCb)
84+
})
85+
86+
after(() => {
87+
server.close()
88+
return agent.close({ ritmReset: false })
89+
})
90+
91+
it('should publish to handleChannel on request', async () => {
92+
const res = await axios.get(`http://localhost:${port}/test`)
93+
94+
expect(res.data).to.equal('OK')
95+
sinon.assert.called(handleChannelCb)
96+
})
97+
98+
it('should publish to routeChannel when middleware is invoked', async () => {
99+
const res = await axios.get(`http://localhost:${port}/test`)
100+
101+
expect(res.data).to.equal('OK')
102+
sinon.assert.called(routeChannelCb)
103+
expect(middlewareCalled).to.be.calledOnce
104+
})
105+
106+
it('should publish to enterChannel when middleware starts', async () => {
107+
const res = await axios.get(`http://localhost:${port}/test`)
108+
109+
expect(res.data).to.equal('OK')
110+
sinon.assert.called(enterChannelCb)
111+
const callArgs = enterChannelCb.firstCall.args[0]
112+
expect(callArgs).to.have.property('req')
113+
expect(callArgs).to.have.property('name')
114+
})
115+
116+
it('should publish to exitChannel when middleware exits', async () => {
117+
const res = await axios.get(`http://localhost:${port}/test`)
118+
119+
expect(res.data).to.equal('OK')
120+
sinon.assert.called(exitChannelCb)
121+
const callArgs = exitChannelCb.firstCall.args[0]
122+
expect(callArgs).to.have.property('req')
123+
})
124+
125+
it('should publish to finishChannel when middleware completes', async () => {
126+
const res = await axios.get(`http://localhost:${port}/test`)
127+
128+
expect(res.data).to.equal('OK')
129+
sinon.assert.called(finishChannelCb)
130+
const callArgs = finishChannelCb.firstCall.args[0]
131+
expect(callArgs).to.have.property('req')
132+
})
133+
134+
it('should publish to nextChannel when next() is called', async () => {
135+
const res = await axios.get(`http://localhost:${port}/test`)
136+
137+
expect(res.data).to.equal('OK')
138+
sinon.assert.called(nextChannelCb)
139+
const callArgs = nextChannelCb.firstCall.args[0]
140+
expect(callArgs).to.have.property('req')
141+
})
142+
143+
it('should publish to errorChannel when middleware throws', async () => {
144+
try {
145+
await axios.get(`http://localhost:${port}/error`)
146+
} catch (e) {
147+
// Expected to fail
148+
}
149+
150+
sinon.assert.called(errorChannelCb)
151+
const callArgs = errorChannelCb.firstCall.args[0]
152+
expect(callArgs).to.have.property('req')
153+
expect(callArgs).to.have.property('error')
154+
expect(callArgs.error.message).to.equal('test error')
155+
})
156+
})
157+
})

0 commit comments

Comments
 (0)