Skip to content

Commit bf7fd94

Browse files
authored
feat(server): added prometheus metrics to messaging server (#546)
1 parent ba628dd commit bf7fd94

File tree

9 files changed

+515
-28
lines changed

9 files changed

+515
-28
lines changed

Dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ RUN yarn workspaces focus --all --production
3636

3737
ENV NODE_ENV=production
3838

39-
ENTRYPOINT [ "yarn", "node", "./packages/server/dist/index.js" ]
40-
CMD []
39+
ENTRYPOINT [ "yarn", "node", "-r", "@bpinternal/trail/init", "./packages/server/dist/index.js" ]
40+
CMD []

packages/framework/src/entry.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export abstract class Entry {
2020
api: IApi
2121
stream: IStream
2222
socket: ISocket
23+
interceptor: IInterceptor
2324

2425
manager: ApiManager
2526
adminManager: AdminApiManager
@@ -29,13 +30,15 @@ export abstract class Entry {
2930
tapp: { new (): IApp },
3031
tapi: { new (app: IApp & any, manager: ApiManager, adminManager: AdminApiManager, express: Express): IApi },
3132
tstream: { new (app: IApp & any): IStream },
32-
tsocket: { new (app: IApp & any): ISocket }
33+
tsocket: { new (app: IApp & any): ISocket },
34+
tinterceptor: { new (app: IApp & any, express: Express): IInterceptor }
3335
) {
3436
this.router = express()
3537
this.router.disable('x-powered-by')
3638
this.routes = new Routes(this.router)
3739

3840
this.app = new tapp()
41+
this.interceptor = new tinterceptor(this.app, this.router)
3942

4043
const auth = new Auth(this.app.clientTokens)
4144
this.manager = new ApiManager(this.routes.router, auth)
@@ -49,6 +52,8 @@ export abstract class Entry {
4952
}
5053

5154
async setup() {
55+
await this.interceptor.setup()
56+
5257
await this.app.prepare(this.package, this.migrations)
5358
await this.app.setup()
5459
await this.app.postSetup()
@@ -98,3 +103,7 @@ interface ISocket {
98103
start(server: Server): Promise<void>
99104
destroy(): Promise<void>
100105
}
106+
107+
interface IInterceptor {
108+
setup(): Promise<void>
109+
}

packages/server/package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
"scripts": {
77
"build": "yarn && yarn run -T tsc --build",
88
"watch": "yarn && yarn run -T tsc --build --watch",
9-
"start": "node ./dist/index.js",
9+
"start": "node -r @bpinternal/trail/init ./dist/index.js",
1010
"dev": "yarn && yarn run -T ts-node-dev --debounce 500 --transpile-only ./src/index.ts"
1111
},
1212
"devDependencies": {
13+
"@promster/types": "^3.2.4",
1314
"@types/cli-color": "^2.0.2",
1415
"@types/cors": "^2.8.12",
1516
"@types/express": "^4.17.13",
@@ -26,7 +27,8 @@
2627
"@botpress/messaging-channels-legacy": "npm:@botpress/[email protected]",
2728
"@botpress/messaging-engine": "1.2.0",
2829
"@botpress/messaging-framework": "1.2.0",
29-
"@bpinternal/trail": "^0.0.1",
30+
"@bpinternal/promex": "^0.5.0",
31+
"@bpinternal/trail": "^0.1.0",
3032
"@opentelemetry/instrumentation-aws-sdk": "0.7.0",
3133
"@opentelemetry/instrumentation-express": "0.27.0",
3234
"@opentelemetry/instrumentation-http": "0.27.0",

packages/server/src/app.ts

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { HealthService } from './health/service'
88
import { InstanceService } from './instances/service'
99
import { MappingService } from './mapping/service'
1010
import { MessageService } from './messages/service'
11+
import { MetricsService } from './metrics/service'
1112
import { ProviderService } from './providers/service'
1213
import { ProvisionService } from './provisions/service'
1314
import { SocketService } from './socket/service'
@@ -35,6 +36,7 @@ export class App extends Framework {
3536
health: HealthService
3637
sockets: SocketService
3738
billing: BillingService
39+
metrics: MetricsService
3840

3941
constructor() {
4042
super()
@@ -93,6 +95,7 @@ export class App extends Framework {
9395
)
9496
this.sockets = new SocketService(this.caching, this.users)
9597
this.billing = new BillingService(this.logger, this.conversations, this.messages)
98+
this.metrics = new MetricsService(this.conversations, this.messages)
9699
}
97100

98101
async setup() {
@@ -112,6 +115,7 @@ export class App extends Framework {
112115
await this.instances.setup()
113116
await this.health.setup()
114117
await this.sockets.setup()
118+
await this.metrics.setup()
115119
}
116120

117121
async postSetup() {
@@ -130,5 +134,6 @@ export class App extends Framework {
130134
await super.destroy()
131135
await this.billing?.destroy()
132136
await this.instances?.destroy()
137+
await this.metrics?.destroy()
133138
}
134139
}

packages/server/src/global.ts

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export type MessagingEnv = FrameworkEnv & {
1010
ENABLE_BILLING_STATS?: string
1111
DISABLE_SOCKETS?: string
1212
ENABLE_LEGACY_CHANNELS?: string
13+
METRICS_ENABLED?: string
14+
METRICS_PORT?: string
1315
}
1416

1517
declare global {

packages/server/src/index.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
/* eslint-disable import/order */
2-
import { init } from '@bpinternal/trail'
3-
init()
4-
51
import './rewire'
62
import { Entry, start } from '@botpress/messaging-framework'
73
import { Api } from './api'
84
import { App } from './app'
5+
import { Interceptor } from './interceptor'
96
import { Migrations } from './migrations'
107
import { Socket } from './socket'
118
import { Stream } from './stream'
12-
/* eslint-enable import/order */
139

1410
export class Root extends Entry {
1511
get name() {
@@ -29,7 +25,7 @@ export class Root extends Entry {
2925
}
3026

3127
constructor() {
32-
super(App, Api, Stream, Socket)
28+
super(App, Api, Stream, Socket, Interceptor)
3329
}
3430
}
3531

packages/server/src/interceptor.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { Express } from 'express'
2+
import { App } from './app'
3+
4+
export class Interceptor {
5+
constructor(private app: App, private express: Express) {}
6+
7+
async setup() {
8+
this.app.metrics.init(this.express)
9+
}
10+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Service } from '@botpress/messaging-engine'
2+
import * as promex from '@bpinternal/promex'
3+
import { defaultNormalizers } from '@promster/express'
4+
import type { Express } from 'express'
5+
import client from 'prom-client'
6+
import yn from 'yn'
7+
import { ConversationEvents } from '../conversations/events'
8+
import { ConversationService } from '../conversations/service'
9+
import { MessageEvents } from '../messages/events'
10+
import { MessageService } from '../messages/service'
11+
12+
const messagesCount = new client.Counter({
13+
name: 'messages_total',
14+
help: 'Counter of all messages.'
15+
})
16+
17+
const conversationsCount = new client.Counter({
18+
name: 'conversations_total',
19+
help: 'Counter of all conversations.'
20+
})
21+
22+
export class MetricsService extends Service {
23+
private metricsEnabled: boolean
24+
private port: number
25+
26+
constructor(private conversations: ConversationService, private messages: MessageService) {
27+
super()
28+
this.metricsEnabled = yn(process.env.METRICS_ENABLED) ?? false
29+
this.port = process.env.METRICS_PORT ? parseInt(process.env.METRICS_PORT) : 9090
30+
}
31+
32+
async destroy() {
33+
if (!this.metricsEnabled) {
34+
return
35+
}
36+
37+
await promex.stop()
38+
}
39+
40+
init(app: Express) {
41+
if (!this.metricsEnabled) {
42+
return
43+
}
44+
45+
promex.config({ normalizePath: defaultNormalizers.normalizePath })
46+
promex.init(app)
47+
}
48+
49+
async setup() {
50+
if (!this.metricsEnabled) {
51+
return
52+
}
53+
54+
this.messages.events.on(MessageEvents.Created, this.handleMessageCreated.bind(this))
55+
this.conversations.events.on(ConversationEvents.Created, this.handleConversationCreated.bind(this))
56+
57+
await promex.start({ port: this.port })
58+
}
59+
60+
private async handleMessageCreated() {
61+
messagesCount.inc()
62+
}
63+
64+
private async handleConversationCreated() {
65+
conversationsCount.inc()
66+
}
67+
}

0 commit comments

Comments
 (0)