Skip to content

Commit

Permalink
feat(server): add db metrics to GQL finished log entries (#3826)
Browse files Browse the repository at this point in the history
* feat(server): add db metrics to GQL finished log entries

* logging for query errored as well
  • Loading branch information
fabis94 authored Jan 15, 2025
1 parent 04c5775 commit cf7f259
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
23 changes: 22 additions & 1 deletion packages/server/logging/knexMonitoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,14 @@ const initKnexPrometheusMetricsForRegionEvents = async (params: {

const trace = (new Error().stack || '').split('\n').slice(1).join('\n').trim()
const reqCtx = getRequestContext()

// Update reqCtx with DB query metrics
if (reqCtx) {
reqCtx.dbMetrics.totalCount++
reqCtx.dbMetrics.totalDuration += durationMs || 0
reqCtx.dbMetrics.queries.push(data.sql)
}

params.logger.info(
{
region,
Expand Down Expand Up @@ -246,6 +254,17 @@ const initKnexPrometheusMetricsForRegionEvents = async (params: {
})
.observe(durationSec)
metricQueryErrors.inc()

const trace = (new Error().stack || '').split('\n').slice(1).join('\n').trim()
const reqCtx = getRequestContext()

// Update reqCtx with DB query metrics
if (reqCtx) {
reqCtx.dbMetrics.totalCount++
reqCtx.dbMetrics.totalDuration += durationMs || 0
reqCtx.dbMetrics.queries.push(data.sql)
}

params.logger.warn(
{
err: typeof err === 'object' ? omit(err, 'detail') : err,
Expand All @@ -254,7 +273,9 @@ const initKnexPrometheusMetricsForRegionEvents = async (params: {
sqlMethod: normalizeSqlMethod(data.method),
sqlQueryId: queryId,
sqlQueryDurationMs: toNDecimalPlaces(durationMs, 0),
sqlNumberBindings: data.bindings?.length || -1
sqlNumberBindings: data.bindings?.length || -1,
trace,
...(reqCtx ? { req: { id: reqCtx.requestId } } : {})
},
'DB query errored for {sqlMethod} after {sqlQueryDurationMs}ms'
)
Expand Down
14 changes: 13 additions & 1 deletion packages/server/logging/requestContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { AsyncLocalStorage } from 'node:async_hooks'

type StorageType = {
requestId: string
dbMetrics: {
totalDuration: number
totalCount: number
queries: string[]
}
}

const storage = asyncRequestContextEnabled()
Expand All @@ -17,7 +22,14 @@ export const initiateRequestContextMiddleware: express.RequestHandler = (
next
) => {
const reqId = req.headers[REQUEST_ID_HEADER] || 'unknown'
const store: StorageType = { requestId: reqId as string }
const store: StorageType = {
requestId: reqId as string,
dbMetrics: {
totalCount: 0,
totalDuration: 0,
queries: []
}
}
storage?.enterWith(store)
next()
}
Expand Down
31 changes: 24 additions & 7 deletions packages/server/modules/core/graph/plugins/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FieldNode, SelectionNode } from 'graphql'
import { ApolloServerPlugin } from '@apollo/server'
import { GraphQLContext } from '@/modules/shared/helpers/typeHelper'
import { shouldLogAsInfoLevel } from '@/logging/graphqlError'
import { getRequestContext } from '@/logging/requestContext'

type ApolloLoggingPluginTransaction = {
start: number
Expand Down Expand Up @@ -62,7 +63,9 @@ export const loggingPluginFactory: (deps: {
const auth = ctx.contextValue
const userId = auth?.userId

const actionName = `${ctx.operation.operation} ${firstSelectedField.name.value}`
const operationName = ctx.operationName || ctx.operation?.name?.value
const actionName =
operationName || `${ctx.operation.operation} ${firstSelectedField.name.value}`
const op = `GQL ${actionName}`
const name = `GQL ${firstSelectedField.name.value}`
const kind = ctx.operation.operation
Expand All @@ -73,8 +76,8 @@ export const loggingPluginFactory: (deps: {
graphql_operation_kind: kind,
graphql_query: query,
graphql_variables: redactSensitiveVariables(variables),
graphql_operation_value: op,
graphql_operation_name: name,
graphql_operation_name: actionName,
graphql_operation_title: op,
userId
})

Expand Down Expand Up @@ -109,6 +112,13 @@ export const loggingPluginFactory: (deps: {
const query = ctx.request.query
const variables = redactSensitiveVariables(ctx.request.variables)

const reqCtx = getRequestContext()
if (reqCtx) {
logger = logger.child({
dbMetrics: reqCtx.dbMetrics
})
}

if (err.path) {
logger = logger.child({
'query-path': err.path.join(' > '),
Expand All @@ -120,28 +130,35 @@ export const loggingPluginFactory: (deps: {
if (shouldLogAsInfoLevel(err)) {
logger.info(
{ err },
'{graphql_operation_value} failed after {apollo_query_duration_ms} ms'
'{graphql_operation_title} failed after {apollo_query_duration_ms} ms'
)
} else {
logger.error(
err,
'{graphql_operation_value} failed after {apollo_query_duration_ms} ms'
'{graphql_operation_title} failed after {apollo_query_duration_ms} ms'
)
}
}
},
willSendResponse: async (ctx) => {
const logger = ctx.contextValue.log || graphqlLogger
let logger = ctx.contextValue.log || graphqlLogger

if (ctx.request.transaction) {
ctx.request.transaction.finish()
}

const reqCtx = getRequestContext()
if (reqCtx) {
logger = logger.child({
dbMetrics: reqCtx.dbMetrics
})
}

logger.info(
{
apollo_query_duration_ms: Date.now() - apolloRequestStart
},
'{graphql_operation_value} finished after {apollo_query_duration_ms} ms'
'{graphql_operation_title} finished after {apollo_query_duration_ms} ms'
)
}
}
Expand Down

0 comments on commit cf7f259

Please sign in to comment.