I'm wanting to provide standardised/shareable logging for my Lambda functions and after reading this article on Decorated Lambda handlers I wondered if Middy would offer a solution.
I thought about for this a bit and then started to have some doubts. Middy would clearly provide a great solution if I wanted to do some standardised logging _around_ each Lambda invocation, but what I really want to do is provide a logger object that is available to Lambda's that would use my middleware.
I scanned the documentation and looked at the implementation of some middlewares and I couldn't find a clear pattern for this or even be sure if this was endorsed. Looking through opened and closed issues I still came away unsure. Based on that I thought I'd raise the issue to ask.
Essentially I want to write a middleware that supports New Relic logging, which means it would provide a Winston logger with @newrelic/winston-enricher, i.e.: my middleware would create a logger and make this available to other middleware and wrapped lambdas.
So how should I do this?:
logger to event?logger to context?next would be nice, e.g. next(null, { logger });?Hello @wrumsby
Thanks for playing with middy and reaching out here.
Is your logger instance going to be a single global object across all your lambdas (singleton)?
If that's the case you wouldn't need to create a dedicated middleware for it, simply instantiate the logger in a module and require the module when needed.
If instead, you need to create a dedicated instance per lambda invocation then you can indeed create a custom middleware that creates the logger in the before phase and attaches it to the handler object.
Let me know if this helps
Hi @lbertenasco I'm interested in the second case - I'll try something that uses that approach.
Thanks.
Hey @wrumsby :) you tagged the other luciano :) This is the one you meant: @lmammino
Cheers!
@lmammino that approach works using JavaScript. Thanks!
My next challenge is trying to create something that works with TypeScript so that the wrapped handler knows that a logger is available.
Any updates on this?
@wrumsby were you successful in writing a middleware? If it's been open-sourced, we could add it to our community list for others to use and give feedback on if you like. Looks like there is interest.
I am new to middy and hit this. My solution is
import {
APIGatewayEvent,
APIGatewayProxyEvent,
APIGatewayProxyResult,
} from 'aws-lambda/trigger/api-gateway-proxy'
import { Context } from 'aws-lambda/handler'
export const handler = middy(
async (event: APIGatewayProxyEvent, _context: Context): Promise<APIGatewayProxyResult> => {
event.log.info('Executing')
return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }
})
.use(loggingMiddlware)
const loggingMiddlware: middy.MiddlewareObject<APIGatewayEvent, APIGatewayProxyResult> = {
async before(handler, _next) {
handler.event.log = globalLogger.child({ requestId: event.requestId })
},
}
declare module 'aws-lambda/trigger/api-gateway-proxy' {
interface APIGatewayProxyEventBase<TAuthorizerContext> {
log: Logger
// Hack so TAuthorizerContext is used, cannot prefix with _
// as it must match the interface exactly for interface merging
___: TAuthorizerContext
}
}
Most helpful comment
Hey @wrumsby :) you tagged the other luciano :) This is the one you meant: @lmammino
Cheers!