11import { createBullBoard } from '@bull-board/api' ;
2- import { BullMQAdapter } from '@bull-board/api/bullMQAdapter.js ' ;
2+ import { BullMQAdapter } from '@bull-board/api/bullMQAdapter' ;
33import { ExpressAdapter } from '@bull-board/express' ;
4+ import {
5+ MetricsRecorder ,
6+ RedisMetricsHistoryProvider ,
7+ } from '@bull-board/metrics' ;
48import { Octokit } from '@octokit/rest' ;
59import * as Sentry from "@sentry/node" ;
610import { PrismaClient , RepoIndexingJobType } from '@sourcebot/db' ;
711import { createLogger , env , JOB_PRIORITIES } from '@sourcebot/shared' ;
812import express , { NextFunction , Request , Response } from 'express' ;
913import 'express-async-errors' ;
14+ import type { Redis } from 'ioredis' ;
1015import * as http from "http" ;
1116import z from 'zod' ;
1217import { SINGLE_TENANT_ORG_ID } from './constants.js' ;
@@ -22,21 +27,41 @@ const PORT = Number(workerApiUrl.port) || (workerApiUrl.protocol === "https:" ?
2227
2328export class Api {
2429 private server : http . Server ;
30+ private metricsRecorder : MetricsRecorder ;
31+ private metricsHistoryProvider : RedisMetricsHistoryProvider ;
2532
2633 constructor (
2734 promClient : PromClient ,
2835 private prisma : PrismaClient ,
2936 private jobManager : JobManager ,
37+ redis : Redis ,
3038 ) {
3139 const app = express ( ) ;
3240 app . use ( express . json ( ) ) ;
3341 app . use ( express . urlencoded ( { extended : true } ) ) ;
3442
3543 const bullBoardAdapter = new ExpressAdapter ( ) ;
3644 bullBoardAdapter . setBasePath ( '/admin/queues' ) ;
45+ const queueAdapters = jobManager
46+ . getQueues ( )
47+ . map ( queue => new BullMQAdapter ( queue ) ) ;
48+ this . metricsHistoryProvider = new RedisMetricsHistoryProvider ( {
49+ connection : redis ,
50+ } ) ;
51+ this . metricsRecorder = new MetricsRecorder ( {
52+ queues : queueAdapters ,
53+ connection : redis ,
54+ onLatencyError : ( error , queueName ) => {
55+ logger . error (
56+ `Failed to record BullMQ latency metrics for queue "${ queueName } "` ,
57+ error ,
58+ ) ;
59+ } ,
60+ } ) ;
3761 createBullBoard ( {
38- queues : jobManager . getQueues ( ) . map ( queue => new BullMQAdapter ( queue , { readOnlyMode : true } ) ) ,
62+ queues : queueAdapters ,
3963 serverAdapter : bullBoardAdapter ,
64+ options : { historyProvider : this . metricsHistoryProvider } ,
4065 } ) ;
4166 app . use ( '/admin/queues' , bullBoardAdapter . getRouter ( ) ) ;
4267
@@ -58,6 +83,7 @@ export class Api {
5883 logger . debug ( `API server is running on port ${ PORT } ` ) ;
5984 logger . debug ( `Bull Board is available at ${ workerApiUrl . origin } /admin/queues` ) ;
6085 } ) ;
86+ this . metricsRecorder . start ( ) ;
6187 }
6288
6389 private async experimental_addGithubRepo ( req : Request , res : Response ) {
@@ -125,6 +151,9 @@ export class Api {
125151 }
126152
127153 public async dispose ( ) {
154+ this . metricsRecorder . stop ( ) ;
155+ this . metricsHistoryProvider . disconnect ( ) ;
156+
128157 return new Promise < void > ( ( resolve , reject ) => {
129158 this . server . close ( ( err ) => {
130159 if ( err ) reject ( err ) ;
0 commit comments