-
Notifications
You must be signed in to change notification settings - Fork 154
Fix(metrics): decorated class methods cannot access this
#1059
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
c6f5f5e
62cd39a
c0b95fe
56dd309
6eebd7a
0879acf
1b6715b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -269,15 +269,20 @@ You can add default dimensions to your metrics by passing them as parameters in | |
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); | ||
const DEFAULT_DIMENSIONS = { 'environment': 'prod', 'foo': 'bar' }; | ||
|
||
export class MyFunction implements LambdaInterface { | ||
export class Lambda implements LambdaInterface { | ||
// Decorate your handler class method | ||
@metrics.logMetrics({ defaultDimensions: DEFAULT_DIMENSIONS }) | ||
public async handler(_event: any, _context: any): Promise<void> { | ||
metrics.addMetric('successfulBooking', MetricUnits.Count, 1); | ||
} | ||
} | ||
|
||
export const handlerClass = new Lambda(); | ||
export const handler = handlerClass.handler.bind(handlerClass); // (1) | ||
``` | ||
|
||
1. Binding your handler method allows your handler to access `this` within the class methods. | ||
|
||
If you'd like to remove them at some point, you can use the `clearDefaultDimensions` method. | ||
|
||
### Flushing metrics | ||
|
@@ -362,15 +367,20 @@ The `logMetrics` decorator of the metrics utility can be used when your Lambda h | |
|
||
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); | ||
|
||
export class MyFunction implements LambdaInterface { | ||
class Lambda implements LambdaInterface { | ||
|
||
@metrics.logMetrics() | ||
public async handler(_event: any, _context: any): Promise<void> { | ||
metrics.addMetric('successfulBooking', MetricUnits.Count, 1); | ||
} | ||
} | ||
|
||
export const handlerClass = new Lambda(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
export const handler = handlerClass.handler.bind(handlerClass); // (1) | ||
``` | ||
|
||
1. Binding your handler method allows your handler to access `this` within the class methods. | ||
|
||
=== "Example CloudWatch Logs excerpt" | ||
|
||
```json hl_lines="2 7 10 15 22" | ||
|
@@ -629,6 +639,8 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `singleMetr | |
} | ||
} | ||
|
||
export const myFunction = new Lambda(); | ||
export const handler = myFunction.handler; | ||
export const handlerClass = new Lambda(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
export const handler = handlerClass.handler.bind(handlerClass); // (1) | ||
``` | ||
|
||
1. Binding your handler method allows your handler to access `this` within the class methods. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import { Metrics, MetricUnits } from '../../src'; | ||
import { Context } from 'aws-lambda'; | ||
import { LambdaInterface } from '../../examples/utils/lambda/LambdaInterface'; | ||
import { LambdaInterface } from '@aws-lambda-powertools/commons'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't this use the published version instead of local version? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I understand, given that we are inside the NPM workspace & it uses the only lock file that is present at the root, then no, it should get the local one (see screenshot below): There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
const namespace = process.env.EXPECTED_NAMESPACE ?? 'CdkExample'; | ||
const serviceName = process.env.EXPECTED_SERVICE_NAME ?? 'MyFunctionWithStandardHandler'; | ||
|
@@ -19,21 +19,28 @@ const metrics = new Metrics({ namespace: namespace, serviceName: serviceName }); | |
class Lambda implements LambdaInterface { | ||
|
||
@metrics.logMetrics({ captureColdStartMetric: true, defaultDimensions: JSON.parse(defaultDimensions), throwOnEmptyMetrics: true }) | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
public async handler(_event: unknown, _context: Context): Promise<void> { | ||
metrics.addMetric(metricName, metricUnit, parseInt(metricValue)); | ||
metrics.addDimension( | ||
Object.entries(JSON.parse(extraDimension))[0][0], | ||
Object.entries(JSON.parse(extraDimension))[0][1] as string, | ||
); | ||
|
||
|
||
this.dummyMethod(); | ||
} | ||
|
||
private dummyMethod(): void { | ||
const metricWithItsOwnDimensions = metrics.singleMetric(); | ||
metricWithItsOwnDimensions.addDimension( | ||
Object.entries(JSON.parse(singleMetricDimension))[0][0], | ||
Object.entries(JSON.parse(singleMetricDimension))[0][1] as string, | ||
); | ||
|
||
metricWithItsOwnDimensions.addMetric(singleMetricName, singleMetricUnit, parseInt(singleMetricValue)); | ||
} | ||
} | ||
|
||
export const handlerClass = new Lambda(); | ||
export const handler = handlerClass.handler; | ||
export const handler = handlerClass.handler.bind(handlerClass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question(nit): do we we need to export the the Lambda class and the constant handlerClass in these examples?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically we don't as long as the customer specifies the correct exported one in the function config (
handler
) in this case.As you saw from the diff in the other files we were already doing so.