feat(api): improve logging with loki and grafana
This commit is contained in:
parent
33cfe91461
commit
f284f74734
@ -1,17 +1,19 @@
|
||||
import type { UserOutput } from '@boring.tools/schema'
|
||||
import { sentry } from '@hono/sentry'
|
||||
// import { sentry } from '@hono/sentry'
|
||||
import { OpenAPIHono, type z } from '@hono/zod-openapi'
|
||||
import { apiReference } from '@scalar/hono-api-reference'
|
||||
import { cors } from 'hono/cors'
|
||||
import { requestId } from 'hono/request-id'
|
||||
|
||||
import changelog from './changelog'
|
||||
import user from './user'
|
||||
|
||||
import { accessTokenApi } from './access-token'
|
||||
import pageApi from './page'
|
||||
import statisticApi from './statistic'
|
||||
import userApi from './user'
|
||||
import { authentication } from './utils/authentication'
|
||||
import { handleError, handleZodError } from './utils/errors'
|
||||
import { logger } from './utils/logger'
|
||||
import { startup } from './utils/startup'
|
||||
|
||||
type User = z.infer<typeof UserOutput>
|
||||
@ -31,9 +33,12 @@ export const app = new OpenAPIHono<{ Variables: Variables }>({
|
||||
// dsn: 'https://1d7428bbab0a305078cf4aa380721aa2@o4508167321354240.ingest.de.sentry.io/4508167323648080',
|
||||
// }),
|
||||
// )
|
||||
|
||||
app.onError(handleError)
|
||||
app.use('*', cors())
|
||||
app.use('/v1/*', authentication)
|
||||
app.use('*', requestId())
|
||||
app.use(logger())
|
||||
app.openAPIRegistry.registerComponent('securitySchemes', 'AccessToken', {
|
||||
type: 'http',
|
||||
scheme: 'bearer',
|
||||
@ -43,7 +48,7 @@ app.openAPIRegistry.registerComponent('securitySchemes', 'Clerk', {
|
||||
scheme: 'bearer',
|
||||
})
|
||||
|
||||
app.route('/v1/user', user)
|
||||
app.route('/v1/user', userApi)
|
||||
app.route('/v1/changelog', changelog)
|
||||
app.route('/v1/page', pageApi)
|
||||
app.route('/v1/access-token', accessTokenApi)
|
||||
|
59
apps/api/src/utils/logger.ts
Normal file
59
apps/api/src/utils/logger.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { db, user } from '@boring.tools/database'
|
||||
import { logger as log } from '@boring.tools/logger'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import type { MiddlewareHandler } from 'hono'
|
||||
import { getPath } from 'hono/utils/url'
|
||||
|
||||
export const logger = (): MiddlewareHandler => {
|
||||
return async function logga(c, next) {
|
||||
const { method } = c.req
|
||||
const clerkUser = c.get('clerkAuth')
|
||||
const requestId = c.get('requestId')
|
||||
const [dbUser] = await db
|
||||
.select({ id: user.id, providerId: user.providerId })
|
||||
.from(user)
|
||||
.where(eq(user.providerId, clerkUser?.userId))
|
||||
const path = getPath(c.req.raw)
|
||||
|
||||
log.info('Incoming', {
|
||||
direction: 'in',
|
||||
method,
|
||||
path,
|
||||
userId: dbUser.id,
|
||||
requestId,
|
||||
})
|
||||
|
||||
await next()
|
||||
|
||||
if (c.res.status <= 399) {
|
||||
log.info('Outgoing', {
|
||||
direction: 'out',
|
||||
method,
|
||||
path,
|
||||
status: c.res.status,
|
||||
userId: dbUser.id,
|
||||
requestId,
|
||||
})
|
||||
}
|
||||
|
||||
if (c.res.status >= 400 && c.res.status < 499) {
|
||||
log.warn('Outgoing', {
|
||||
direction: 'out',
|
||||
method,
|
||||
path,
|
||||
status: c.res.status,
|
||||
requestId,
|
||||
})
|
||||
}
|
||||
|
||||
if (c.res.status >= 500) {
|
||||
log.error('Outgoing', {
|
||||
direction: 'out',
|
||||
method,
|
||||
path,
|
||||
status: c.res.status,
|
||||
requestId,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
"@logtail/node": "^0.5.0",
|
||||
"@logtail/winston": "^0.5.0",
|
||||
"winston": "^3.14.2",
|
||||
"winston-console-format": "^1.0.8",
|
||||
"winston-loki": "^6.1.3"
|
||||
}
|
||||
}
|
@ -1,20 +1,41 @@
|
||||
import { Logtail } from '@logtail/node'
|
||||
import { LogtailTransport } from '@logtail/winston'
|
||||
import winston from 'winston'
|
||||
import { createLogger, format, transports } from 'winston'
|
||||
import { consoleFormat } from 'winston-console-format'
|
||||
import LokiTransport from 'winston-loki'
|
||||
|
||||
// Create a Winston logger - passing in the Logtail transport
|
||||
export const logger = winston.createLogger({
|
||||
format: winston.format.json(),
|
||||
export const logger = createLogger({
|
||||
format: format.combine(
|
||||
format.timestamp(),
|
||||
format.ms(),
|
||||
format.errors({ stack: true }),
|
||||
format.splat(),
|
||||
format.json(),
|
||||
),
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
format: winston.format.json(),
|
||||
new transports.Console({
|
||||
format: format.combine(
|
||||
format.colorize({ all: true }),
|
||||
format.padLevels(),
|
||||
consoleFormat({
|
||||
showMeta: true,
|
||||
metaStrip: ['timestamp', 'service'],
|
||||
inspectOptions: {
|
||||
depth: Number.POSITIVE_INFINITY,
|
||||
colors: true,
|
||||
maxArrayLength: Number.POSITIVE_INFINITY,
|
||||
breakLength: 120,
|
||||
compact: Number.POSITIVE_INFINITY,
|
||||
},
|
||||
}),
|
||||
),
|
||||
}),
|
||||
new LokiTransport({
|
||||
host: 'http://localhost:9100',
|
||||
labels: { app: 'api' },
|
||||
json: true,
|
||||
format: winston.format.json(),
|
||||
labels: { service: 'api' },
|
||||
format: format.json(),
|
||||
replaceTimestamp: true,
|
||||
onConnectionError: (err) => console.error(err),
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user