Skip to content

Commit e6c2808

Browse files
authored
refactor: add debug-level lib for granular log leveling (#419)
* refactor: add debug-level lib for granular log leveling * refactor: adapt to new log content format * feat(logging): add logs for improving observability * refactor(pg): rename query binding variables for clarity
1 parent 3bb0d3c commit e6c2808

File tree

49 files changed

+1121
-297
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1121
-297
lines changed

auth/.env.test

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
JWT_SECRET=test
22
JWT_SECRET_ALGORITHM=HS256
3-
API_SECRET=test
3+
API_SECRET=test
4+
DEBUG_LEVEL=error

auth/package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"build": "tsc",
1010
"dev": "nodemon src/index.ts",
1111
"migrate": "db-migrate -t auth_migrations",
12-
"test": "node --experimental-vm-modules ../node_modules/jest/bin/jest.js --runInBand --coverage",
12+
"test": "NODE_OPTIONS='--max-old-space-size=4096' node --experimental-vm-modules ../node_modules/jest/bin/jest.js --runInBand --coverage --forceExit",
1313
"lint": "eslint .",
1414
"lambda:build": "yarn build && ../node_modules/.bin/esbuild src/lambda.ts --bundle --platform=node --target=node18 --outfile=build/index.js"
1515
},
@@ -23,6 +23,7 @@
2323
"cors": "^2.8.5",
2424
"db-migrate": "^0.11.14",
2525
"db-migrate-pg": "^1.5.2",
26+
"debug-level": "^4.1.1",
2627
"dotenv": "^16.4.7",
2728
"esbuild": "^0.25.0",
2829
"express": "^4.21.2",
@@ -31,14 +32,18 @@
3132
"serverless-http": "^3.2.0",
3233
"siwe": "^3.0.0",
3334
"typescript": "^5.7.3",
34-
"uuid": "^11.0.5",
35-
"winston": "^3.17.0"
35+
"uuid": "^11.0.5"
3636
},
3737
"devDependencies": {
3838
"@testcontainers/postgresql": "^10.14.0",
3939
"@testcontainers/rabbitmq": "^10.17.2",
40+
"@types/amqplib": "^0.10.6",
41+
"@types/aws-sdk": "^2.7.0",
4042
"@types/cors": "^2.8.17",
43+
"@types/express": "^5.0.0",
4144
"@types/jest": "^29.5.14",
45+
"@types/multer": "^1.4.12",
46+
"@types/uuid": "^9.0.0",
4247
"db-migrate-plugin-typescript": "^2.0.0",
4348
"eslint": "^8.57.1",
4449
"eslint-config-prettier": "^9.1.0",

auth/src/controllers/user.ts

Lines changed: 93 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Router } from 'express'
1+
import { Router, Request, Response } from 'express'
22
import {
33
handleAdminAuth,
44
handleAuth,
@@ -9,11 +9,13 @@ import { UsersUseCases } from '../useCases/index.js'
99
import { ApiKeysUseCases } from '../useCases/apikeys.js'
1010
import { UserRole } from '@auto-drive/models'
1111
import { CustomJWTAuth } from '../services/authManager/providers/custom.js'
12-
import { logger } from '../drivers/logger.js'
12+
import { createLogger } from '../drivers/logger.js'
13+
14+
const logger = createLogger('controllers:user')
1315

1416
const userController = Router()
1517

16-
userController.post('/@me/onboard', async (req, res) => {
18+
userController.post('/@me/onboard', async (req: Request, res: Response) => {
1719
const user = await handleAuthIgnoreOnboarding(req, res)
1820
if (!user) {
1921
return
@@ -23,14 +25,14 @@ userController.post('/@me/onboard', async (req, res) => {
2325
const onboardedUser = await UsersUseCases.onboardUser(user)
2426
res.json(onboardedUser)
2527
} catch (error) {
26-
console.error(error)
28+
logger.error(error)
2729
res.status(500).json({
2830
error: 'Failed to onboard user',
2931
})
3032
}
3133
})
3234

33-
userController.post('/@me/accessToken', async (req, res) => {
35+
userController.post('/@me/accessToken', async (req: Request, res: Response) => {
3436
const user = await handleAuthIgnoreOnboarding(req, res)
3537
if (!user) {
3638
return
@@ -48,42 +50,49 @@ userController.post('/@me/accessToken', async (req, res) => {
4850
.json({ accessToken })
4951
})
5052

51-
userController.post('/@me/refreshToken', async (req, res) => {
52-
try {
53-
const refreshToken = req.headers.cookie?.match(/refreshToken=([^;]+)/)?.[1]
54-
if (!refreshToken) {
55-
res.status(401).json({
56-
error: 'Unauthorized',
57-
})
53+
userController.post(
54+
'/@me/refreshToken',
55+
async (req: Request, res: Response) => {
56+
try {
57+
const refreshToken =
58+
req.headers.cookie?.match(/refreshToken=([^;]+)/)?.[1]
59+
if (!refreshToken) {
60+
res.status(401).json({
61+
error: 'Unauthorized',
62+
})
63+
return
64+
}
65+
66+
const accessToken = await refreshAccessToken(refreshToken)
67+
68+
res.json({ accessToken })
69+
} catch (error) {
70+
logger.error(error)
71+
res.status(500).json({ error: 'Failed to refresh access token' })
5872
return
5973
}
74+
},
75+
)
6076

61-
const accessToken = await refreshAccessToken(refreshToken)
62-
63-
res.json({ accessToken })
64-
} catch (error) {
65-
console.error(error)
66-
res.status(500).json({ error: 'Failed to refresh access token' })
67-
return
68-
}
69-
})
70-
71-
userController.delete('/@me/invalidateToken', async (req, res) => {
72-
const token = req.body.token
77+
userController.delete(
78+
'/@me/invalidateToken',
79+
async (req: Request, res: Response) => {
80+
const token = req.body.token
7381

74-
if (typeof token !== 'string') {
75-
res.status(400).json({
76-
error: 'Missing or invalid attribute `token` in body',
77-
})
78-
return
79-
}
82+
if (typeof token !== 'string') {
83+
res.status(400).json({
84+
error: 'Missing or invalid attribute `token` in body',
85+
})
86+
return
87+
}
8088

81-
await CustomJWTAuth.invalidateRefreshToken(token)
89+
await CustomJWTAuth.invalidateRefreshToken(token)
8290

83-
res.sendStatus(200)
84-
})
91+
res.sendStatus(200)
92+
},
93+
)
8594

86-
userController.get('/@me', async (req, res) => {
95+
userController.get('/@me', async (req: Request, res: Response) => {
8796
const user = await handleAuthIgnoreOnboarding(req, res)
8897
if (!user) {
8998
logger.warn('User not found')
@@ -95,15 +104,15 @@ userController.get('/@me', async (req, res) => {
95104

96105
res.json(userInfo)
97106
} catch (error) {
98-
console.error(error)
107+
logger.error(error)
99108
res.status(500).json({
100109
error: 'Failed to get user info',
101110
})
102111
return
103112
}
104113
})
105114

106-
userController.get('/@me/apiKeys', async (req, res) => {
115+
userController.get('/@me/apiKeys', async (req: Request, res: Response) => {
107116
const user = await handleAuth(req, res)
108117
if (!user) {
109118
return
@@ -114,55 +123,61 @@ userController.get('/@me/apiKeys', async (req, res) => {
114123

115124
res.json(apiKeys)
116125
} catch (error) {
117-
console.error(error)
126+
logger.error(error)
118127
res.status(500).json({
119128
error: 'Failed to get API keys',
120129
})
121130
return
122131
}
123132
})
124133

125-
userController.post('/@me/apiKeys/create', async (req, res) => {
126-
const user = await handleAuth(req, res)
127-
if (!user) {
128-
return
129-
}
134+
userController.post(
135+
'/@me/apiKeys/create',
136+
async (req: Request, res: Response) => {
137+
const user = await handleAuth(req, res)
138+
if (!user) {
139+
return
140+
}
130141

131-
try {
132-
const apiKey = await ApiKeysUseCases.createApiKey(user)
142+
try {
143+
const apiKey = await ApiKeysUseCases.createApiKey(user)
133144

134-
res.json(apiKey)
135-
} catch (error) {
136-
console.error(error)
137-
res.status(500).json({
138-
error: 'Failed to create API key',
139-
})
140-
return
141-
}
142-
})
143-
144-
userController.delete('/@me/apiKeys/:id', async (req, res) => {
145-
const user = await handleAuth(req, res)
146-
if (!user) {
147-
return
148-
}
145+
res.json(apiKey)
146+
} catch (error) {
147+
logger.error(error)
148+
res.status(500).json({
149+
error: 'Failed to create API key',
150+
})
151+
return
152+
}
153+
},
154+
)
155+
156+
userController.delete(
157+
'/@me/apiKeys/:id',
158+
async (req: Request, res: Response) => {
159+
const user = await handleAuth(req, res)
160+
if (!user) {
161+
return
162+
}
149163

150-
const { id } = req.params
164+
const { id } = req.params
151165

152-
try {
153-
await ApiKeysUseCases.deleteApiKey(user, id)
166+
try {
167+
await ApiKeysUseCases.deleteApiKey(user, id)
154168

155-
res.sendStatus(200)
156-
} catch (error) {
157-
console.error(error)
158-
res.status(500).json({
159-
error: 'Failed to delete API key',
160-
})
161-
return
162-
}
163-
})
169+
res.sendStatus(200)
170+
} catch (error) {
171+
logger.error(error)
172+
res.status(500).json({
173+
error: 'Failed to delete API key',
174+
})
175+
return
176+
}
177+
},
178+
)
164179

165-
userController.post('/admin/add', async (req, res) => {
180+
userController.post('/admin/add', async (req: Request, res: Response) => {
166181
const user = await handleAuth(req, res)
167182
if (!user) {
168183
return
@@ -182,15 +197,15 @@ userController.post('/admin/add', async (req, res) => {
182197

183198
res.sendStatus(200)
184199
} catch (error) {
185-
console.error(error)
200+
logger.error(error)
186201
res.status(500).json({
187202
error: 'Failed to add user to admins',
188203
})
189204
return
190205
}
191206
})
192207

193-
userController.post('/admin/remove', async (req, res) => {
208+
userController.post('/admin/remove', async (req: Request, res: Response) => {
194209
const user = await handleAuth(req, res)
195210
if (!user) {
196211
return
@@ -210,15 +225,15 @@ userController.post('/admin/remove', async (req, res) => {
210225

211226
res.sendStatus(200)
212227
} catch (error) {
213-
console.error(error)
228+
logger.error(error)
214229
res.status(500).json({
215230
error: 'Failed to remove user from admins',
216231
})
217232
return
218233
}
219234
})
220235

221-
userController.get('/list', async (req, res) => {
236+
userController.get('/list', async (req: Request, res: Response) => {
222237
const user = await handleAuth(req, res)
223238
if (!user) {
224239
return
@@ -248,15 +263,15 @@ userController.get('/list', async (req, res) => {
248263

249264
res.json(result)
250265
} catch (error) {
251-
console.error(error)
266+
logger.error(error)
252267
res.status(500).json({
253268
error: 'Failed to get user list',
254269
})
255270
return
256271
}
257272
})
258273

259-
userController.get('/:publicId', async (req, res) => {
274+
userController.get('/:publicId', async (req: Request, res: Response) => {
260275
const { publicId } = req.params
261276

262277
const isAdmin = await handleAdminAuth(req, res)

auth/src/drivers/logger.ts

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { createLogger, format, transports } from 'winston'
2-
import { config } from '../config.js'
1+
import { Log } from 'debug-level'
32

4-
type Any =
3+
export type Any =
54
| object
65
| string
76
| number
@@ -12,29 +11,32 @@ type Any =
1211
| unknown
1312

1413
export interface Logger {
15-
info: (...message: Any[]) => Promise<void>
16-
error: (...message: Any[]) => Promise<void>
17-
warn: (...message: Any[]) => Promise<void>
18-
debug: (...message: Any[]) => Promise<void>
14+
info: (...message: Any[]) => void
15+
error: (...message: Any[]) => void
16+
warn: (...message: Any[]) => void
17+
debug: (...message: Any[]) => void
18+
trace: (...message: Any[]) => void
1919
}
2020

21-
const winstonLogger = createLogger({
22-
level: config.logLevel,
23-
format: format.combine(format.timestamp(), format.json()),
24-
transports: [new transports.Console()],
25-
})
26-
27-
export const logger: Logger = {
28-
info: async (...message: Any[]) => {
29-
winstonLogger.info(message.join(' '))
30-
},
31-
error: async (...message: Any[]) => {
32-
winstonLogger.error(message.join(' '))
33-
},
34-
warn: async (...message: Any[]) => {
35-
winstonLogger.warn(message.join(' '))
36-
},
37-
debug: async (...message: Any[]) => {
38-
winstonLogger.debug(message.join(' '))
39-
},
21+
function wrapLog(log: Log): Logger {
22+
return {
23+
info: (...message: Any[]) => {
24+
log.info(...message)
25+
},
26+
error: (...message: Any[]) => {
27+
log.error(...message)
28+
},
29+
warn: (...message: Any[]) => {
30+
log.warn(...message)
31+
},
32+
debug: (...message: Any[]) => {
33+
log.debug(...message)
34+
},
35+
trace: (...message: Any[]) => {
36+
log.trace(...message)
37+
},
38+
}
4039
}
40+
41+
export const createLogger = (namespace: string): Logger =>
42+
wrapLog(new Log(namespace))

0 commit comments

Comments
 (0)