Skip to content

Instantly share code, notes, and snippets.

@jordanebelanger
Last active June 2, 2023 21:09
Show Gist options
  • Save jordanebelanger/48616ba4ca8d9b050f6f1f5fd207213f to your computer and use it in GitHub Desktop.
Save jordanebelanger/48616ba4ca8d9b050f6f1f5fd207213f to your computer and use it in GitHub Desktop.
stackdriverlogger.ts
import * as P from 'pino'
import {FastifyReply, FastifyRequest} from 'fastify'
const enum PINO_LEVELS {
trace = 10,
debug = 20,
info = 30,
warn = 40,
error = 50,
fatal = 60,
}
const enum StackdriverSeverity {
default = 'DEFAULT',
debug = 'DEBUG',
info = 'INFO',
notice = 'NOTICE',
warning = 'WARNING',
error = 'ERROR',
critical = 'CRITICAL',
alert = 'ALERT',
emergency = 'EMERGENCY'
}
function pinoLevelToStackdriverSeverity(level: PINO_LEVELS): StackdriverSeverity {
switch (level) {
case PINO_LEVELS.trace:
case PINO_LEVELS.debug:
return StackdriverSeverity.debug
case PINO_LEVELS.info:
return StackdriverSeverity.info
case PINO_LEVELS.warn:
return StackdriverSeverity.warning
case PINO_LEVELS.error:
return StackdriverSeverity.error
case PINO_LEVELS.fatal:
return StackdriverSeverity.critical
default:
return StackdriverSeverity.default
}
}
function truncateToDecimalPlace(value: number, decimalPlace: number) {
return (
Math.trunc(value * Math.pow(10, decimalPlace)) / Math.pow(10, decimalPlace)
)
}
interface LogEntryHTTPRequest {
requestMethod?: string
requestUrl?: string
requestSize?: string
status?: number
responseSize?: string
userAgent?: string
remoteIp?: string
serverIp?: string
referer?: string
latency?: string
cacheLookup?: boolean
cacheHit?: boolean
cacheValidatedWithOriginServer?: boolean
cacheFillBytes?: string
protocol?: string
}
interface LogObject {
req?: FastifyRequest
res?: FastifyReply
httpRequest?: LogEntryHTTPRequest
requestId?: string
}
export default function logger(level: P.Level): P.Logger {
return P({
messageKey: 'message',
timestamp: false,
base: undefined,
level: level,
formatters: {
level(_label, number) {
return {
severity: pinoLevelToStackdriverSeverity(number),
}
},
log(object: LogObject) {
// Setuping the Stackdriver httpRequest property on the log entry
if (object.req) {
object.httpRequest = {
...(object.httpRequest ?? {},
{
requestMethod: object.req.method,
requestUrl: object.req.url,
userAgent: object.req.headers['user-agent'],
remoteIp: object.req.ips?.[0] ?? object.req.ip,
protocol: object.req.protocol,
})
}
}
if (object.res) {
object.httpRequest = {
...(object.httpRequest ?? {},
{
requestMethod: object.res.request.method,
requestUrl: object.res.request.url,
status: object.res.statusCode,
userAgent: object.res.request.headers['user-agent'],
latency: `${truncateToDecimalPlace(object.res.getResponseTime() / 1000, 9)}s`,
remoteIp: object.res.request.ips?.[0] ?? object.res.request.ip,
protocol: object.res.request.protocol,
}),
}
}
return object
}
},
serializers: {
// Nullifying the standard Fastify Request/Response serializer for better stackdriver support
req(request: FastifyRequest) { return undefined },
res(reply: FastifyReply) { return undefined },
responseTime: function(value) { return undefined }
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment