Skip to content

Commit 3176fa0

Browse files
feat(metrics): allow setting functionName via constructor parameter and environment variable (#3696)
Co-authored-by: Andrea Amorosi <[email protected]>
1 parent de4d158 commit 3176fa0

File tree

12 files changed

+463
-84
lines changed

12 files changed

+463
-84
lines changed

Diff for: docs/core/metrics.md

+31-7
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ The library requires two settings. You can set them as environment variables, or
6666

6767
These settings will be used across all metrics emitted:
6868

69-
| Setting | Description | Environment variable | Default | Allowed Values | Example | Constructor parameter |
70-
| -------------------- | ---------------------------------------------------------------- | ------------------------------ | ------------------- | -------------- | ------------------- | --------------------- |
71-
| **Service** | Optionally, sets **service** metric dimension across all metrics | `POWERTOOLS_SERVICE_NAME` | `service_undefined` | Any string | `serverlessAirline` | `serviceName` |
72-
| **Metric namespace** | Logical container where all metrics will be placed | `POWERTOOLS_METRICS_NAMESPACE` | `default_namespace` | Any string | `serverlessAirline` | `default_namespace` |
73-
| **Enabled** | Whether to emit metrics to standard output or not | `POWERTOOLS_METRICS_ENABLED` | `true` | Boolean | `false` | |
69+
| Setting | Description | Environment variable | Default | Allowed Values | Example | Constructor parameter |
70+
|----------------------|------------------------------------------------------------------|------------------------------------|----------------------------------------------------------|----------------|---------------------|-----------------------|
71+
| **Service** | Optionally, sets **service** metric dimension across all metrics | `POWERTOOLS_SERVICE_NAME` | `service_undefined` | Any string | `serverlessAirline` | `serviceName` |
72+
| **Metric namespace** | Logical container where all metrics will be placed | `POWERTOOLS_METRICS_NAMESPACE` | `default_namespace` | Any string | `serverlessAirline` | `default_namespace` |
73+
| **Function Name** | Function name used as dimension for the `ColdStart` metric | `POWERTOOLS_METRICS_FUNCTION_NAME` | [See docs](#capturing-a-cold-start-invocation-as-metric) | Any string | `my-function-name` | `functionName` |
74+
| **Enabled** | Whether to emit metrics to standard output or not | `POWERTOOLS_METRICS_ENABLED` | `true` | Boolean | `false` | |
7475

7576
!!! tip
7677
Use your application name or main service as the metric namespace to easily group all metrics
@@ -87,7 +88,7 @@ The `Metrics` utility is instantiated outside of the Lambda handler. In doing th
8788

8889
=== "template.yml"
8990

90-
```yaml hl_lines="9 10"
91+
```yaml hl_lines="8-10"
9192
Resources:
9293
HelloWorldFunction:
9394
Type: AWS::Serverless::Function
@@ -97,6 +98,7 @@ The `Metrics` utility is instantiated outside of the Lambda handler. In doing th
9798
Variables:
9899
POWERTOOLS_SERVICE_NAME: orders
99100
POWERTOOLS_METRICS_NAMESPACE: serverlessAirline
101+
POWERTOOLS_METRICS_FUNCTION_NAME: my-function-name
100102
```
101103

102104
You can initialize Metrics anywhere in your code - It'll keep track of your aggregate metrics in memory.
@@ -184,7 +186,7 @@ You can call `addMetric()` with the same name multiple times. The values will be
184186

185187
### Adding default dimensions
186188

187-
You can add default dimensions to your metrics by passing them as parameters in 4 ways:
189+
You can add default dimensions to your metrics by passing them as parameters in 4 ways:
188190

189191
* in the constructor
190192
* in the [Middy-compatible](https://github.com/middyjs/middy){target=_blank} middleware
@@ -405,6 +407,28 @@ This has the advantage of keeping cold start metric separate from your applicati
405407

406408
!!! info "We do not emit 0 as a value for the ColdStart metric for cost-efficiency reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-typescript/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=) if you'd prefer a flag to override it."
407409

410+
#### Setting function name
411+
412+
When emitting cold start metrics, the `function_name` dimension defaults to `context.functionName`. If you want to change the value you can set the `functionName` parameter in the metrics constructor, define the environment variable `POWERTOOLS_METRICS_FUNCTION_NAME`, or pass a value to `captureColdStartMetric`.
413+
414+
The priority of the `function_name` dimension value is defined as:
415+
416+
1. `functionName` constructor option
417+
2. `POWERTOOLS_METRICS_FUNCTION_NAME` environment variable
418+
3. The value passed in the `captureColdStartMetric` call, or `context.functionName` if using logMetrics decorator or Middy middleware
419+
420+
=== "constructor"
421+
422+
```typescript hl_lines="6"
423+
--8<-- "examples/snippets/metrics/functionName.ts"
424+
```
425+
426+
=== "captureColdStartMetric method"
427+
428+
```typescript hl_lines="12"
429+
--8<-- "examples/snippets/metrics/captureColdStartMetric.ts"
430+
```
431+
408432
## Advanced
409433

410434
### Adding metadata

Diff for: docs/index.md

+17-16
Original file line numberDiff line numberDiff line change
@@ -351,22 +351,23 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al
351351
???+ info
352352
Explicit parameters take precedence over environment variables
353353

354-
| Environment variable | Description | Utility | Default |
355-
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ------------------- |
356-
| **POWERTOOLS_SERVICE_NAME** | Set service name used for tracing namespace, metrics dimension and structured logging | All | `service_undefined` |
357-
| **POWERTOOLS_METRICS_NAMESPACE** | Set namespace used for metrics | [Metrics](core/metrics.md) | `default_namespace` |
358-
| **POWERTOOLS_METRICS_ENABLED** | Explicitly disables emitting metrics to stdout | [Metrics](core/metrics.md) | `true` |
359-
| **POWERTOOLS_TRACE_ENABLED** | Explicitly disables tracing | [Tracer](core/tracer.md) | `true` |
360-
| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Capture Lambda or method return as metadata. | [Tracer](core/tracer.md) | `true` |
361-
| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Capture Lambda or method exception as metadata. | [Tracer](core/tracer.md) | `true` |
362-
| **POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS** | Capture HTTP(s) requests as segments. | [Tracer](core/tracer.md) | `true` |
363-
| **POWERTOOLS_LOGGER_LOG_EVENT** | Log incoming event | [Logger](core/logger.md) | `false` |
364-
| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logger](core/logger.md) | `0` |
365-
| **POWERTOOLS_DEV** | Increase JSON indentation to ease debugging when running functions locally or in a non-production environment | [Logger](core/logger.md) | `false` |
366-
| **POWERTOOLS_LOG_LEVEL** | Sets how verbose Logger should be, from the most verbose to the least verbose (no logs) | [Logger](core/logger.md) | `INFO` |
367-
| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](utilities/parameters.md) | `5` |
368-
| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Set whether to decrypt or not values retrieved from AWS Systems Manager Parameters Store | [Parameters](utilities/parameters.md) | `false` |
369-
| **POWERTOOLS_IDEMPOTENCY_DISABLED** | Disable the Idempotency logic without changing your code, useful for testing | [Idempotency](utilities/idempotency.md) | `false` |
354+
| Environment variable | Description | Utility | Default |
355+
| -------------------------------------------- |------------------------------------------------------------------------------------------| --------------------------------------- |-------------------------------------------------|
356+
| **POWERTOOLS_SERVICE_NAME** | Set service name used for tracing namespace, metrics dimension and structured logging | All | `service_undefined` |
357+
| **POWERTOOLS_METRICS_NAMESPACE** | Set namespace used for metrics | [Metrics](core/metrics.md) | `default_namespace` |
358+
| **POWERTOOLS_METRICS_FUNCTION_NAME** | Function name used as dimension for the `ColdStart` metric | [Metrics](core/metrics.md) | [See docs](core/metrics/#setting-function-name) |
359+
| **POWERTOOLS_METRICS_ENABLED** | Explicitly disables emitting metrics to stdout | [Metrics](core/metrics.md) | `true` |
360+
| **POWERTOOLS_TRACE_ENABLED** | Explicitly disables tracing | [Tracer](core/tracer.md) | `true` |
361+
| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Capture Lambda or method return as metadata. | [Tracer](core/tracer.md) | `true` |
362+
| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Capture Lambda or method exception as metadata. | [Tracer](core/tracer.md) | `true` |
363+
| **POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS** | Capture HTTP(s) requests as segments. | [Tracer](core/tracer.md) | `true` |
364+
| **POWERTOOLS_LOGGER_LOG_EVENT** | Log incoming event | [Logger](core/logger.md) | `false` |
365+
| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logger](core/logger.md) | `0` |
366+
| **POWERTOOLS_DEV** | Pretty-print logs, disable metrics flushing, and disable traces - use for dev only | See section below | `false` |
367+
| **POWERTOOLS_LOG_LEVEL** | Sets how verbose Logger should be, from the most verbose to the least verbose (no logs) | [Logger](core/logger.md) | `INFO` |
368+
| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](utilities/parameters.md) | `5` |
369+
| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Set whether to decrypt or not values retrieved from AWS Systems Manager Parameters Store | [Parameters](utilities/parameters.md) | `false` |
370+
| **POWERTOOLS_IDEMPOTENCY_DISABLED** | Disable the Idempotency logic without changing your code, useful for testing | [Idempotency](utilities/idempotency.md) | `false` |
370371

371372
Each Utility page provides information on example values and allowed values.
372373

Diff for: examples/snippets/metrics/captureColdStartMetric.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { MetricUnit, Metrics } from '@aws-lambda-powertools/metrics';
2+
3+
const metrics = new Metrics({
4+
namespace: 'serverlessAirline',
5+
serviceName: 'orders',
6+
});
7+
8+
export const handler = async (
9+
_event: unknown,
10+
_context: unknown
11+
): Promise<void> => {
12+
metrics.captureColdStartMetric('my-function-name');
13+
14+
metrics.addMetric('successfulBooking', MetricUnit.Count, 1);
15+
16+
metrics.publishStoredMetrics();
17+
};

Diff for: examples/snippets/metrics/functionName.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { MetricUnit, Metrics } from '@aws-lambda-powertools/metrics';
2+
3+
const metrics = new Metrics({
4+
namespace: 'serverlessAirline',
5+
serviceName: 'orders',
6+
functionName: 'my-function-name',
7+
});
8+
9+
export const handler = async (
10+
_event: unknown,
11+
_context: unknown
12+
): Promise<void> => {
13+
metrics.captureColdStartMetric();
14+
15+
metrics.addMetric('successfulBooking', MetricUnit.Count, 1);
16+
17+
metrics.publishStoredMetrics();
18+
};

Diff for: packages/metrics/src/Metrics.ts

+30-25
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,10 @@ class Metrics extends Utility implements MetricsInterface {
371371
* metrics.captureColdStartMetric();
372372
* };
373373
* ```
374+
*
375+
* @param functionName - Optional function name to use as `function_name` dimension in the metric. It's used only if the `functionName` constructor parameter or environment variable are not set.
374376
*/
375-
public captureColdStartMetric(): void {
377+
public captureColdStartMetric(functionName?: string): void {
376378
if (!this.getColdStart()) return;
377379
const singleMetric = this.singleMetric();
378380

@@ -381,8 +383,9 @@ class Metrics extends Utility implements MetricsInterface {
381383
service: this.defaultDimensions.service,
382384
});
383385
}
384-
if (this.functionName != null) {
385-
singleMetric.addDimension('function_name', this.functionName);
386+
const value = this.functionName?.trim() ?? functionName?.trim();
387+
if (value && value.length > 0) {
388+
singleMetric.addDimension('function_name', value);
386389
}
387390
singleMetric.addMetric(COLD_START_METRIC, MetricUnits.Count, 1);
388391
}
@@ -543,8 +546,9 @@ class Metrics extends Utility implements MetricsInterface {
543546
context: Context,
544547
callback: Callback
545548
): Promise<unknown> {
546-
metricsRef.functionName = context.functionName;
547-
if (captureColdStartMetric) metricsRef.captureColdStartMetric();
549+
if (captureColdStartMetric) {
550+
metricsRef.captureColdStartMetric(context.functionName);
551+
}
548552

549553
let result: unknown;
550554
try {
@@ -749,28 +753,14 @@ class Metrics extends Utility implements MetricsInterface {
749753
}
750754

751755
/**
752-
* Set the function name to be added to each metric as a dimension.
753-
*
754-
* When using the {@link Metrics.logMetrics | `logMetrics()`} decorator, or the Middy.js middleware, the function
755-
* name is automatically inferred from the Lambda context.
756-
*
757-
* @example
758-
* ```typescript
759-
* import { Metrics } from '@aws-lambda-powertools/metrics';
760-
*
761-
* const metrics = new Metrics({
762-
* namespace: 'serverlessAirline',
763-
* serviceName: 'orders'
764-
* });
765-
*
766-
* metrics.setFunctionName('my-function-name');
767-
* ```
768-
*
769-
* @param name - The function name
756+
* @deprecated Override the function name for `ColdStart` metrics inferred from the context either via:
757+
* - `functionName` constructor parameter
758+
* - `POWERTOOLS_FUNCTION_NAME` environment variable
759+
* - {@link Metrics.captureColdStartMetric | `captureColdStartMetric('myFunctionName')`} method
770760
*/
771-
public setFunctionName(name: string): void {
761+
/* v8 ignore start */ public setFunctionName(name: string): void {
772762
this.functionName = name;
773-
}
763+
} /* v8 ignore end */
774764

775765
/**
776766
* Set the flag to throw an error if no metrics are emitted.
@@ -917,6 +907,19 @@ class Metrics extends Utility implements MetricsInterface {
917907
this.envVarsService = new EnvironmentVariablesService();
918908
}
919909

910+
/**
911+
* Set the function name for the cold start metric.
912+
*
913+
* @param functionName - The function name to be used for the cold start metric set in the constructor
914+
*/
915+
protected setFunctionNameForColdStartMetric(functionName?: string): void {
916+
const value =
917+
functionName?.trim() ?? this.getEnvVarsService().getFunctionName().trim();
918+
if (value && value.length > 0) {
919+
this.functionName = value;
920+
}
921+
}
922+
920923
/**
921924
* Set the namespace to be used.
922925
*
@@ -951,6 +954,7 @@ class Metrics extends Utility implements MetricsInterface {
951954
serviceName,
952955
singleMetric,
953956
defaultDimensions,
957+
functionName,
954958
} = options;
955959

956960
this.setEnvVarsService();
@@ -960,6 +964,7 @@ class Metrics extends Utility implements MetricsInterface {
960964
this.setNamespace(namespace);
961965
this.setService(serviceName);
962966
this.setDefaultDimensions(defaultDimensions);
967+
this.setFunctionNameForColdStartMetric(functionName);
963968
this.isSingleMetric = singleMetric || false;
964969

965970
return this;

Diff for: packages/metrics/src/config/EnvironmentVariablesService.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class EnvironmentVariablesService
1111
extends CommonEnvironmentVariablesService
1212
implements ConfigServiceInterface
1313
{
14-
private namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE';
15-
14+
private readonly namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE';
15+
private readonly functionNameVariable = 'POWERTOOLS_METRICS_FUNCTION_NAME';
1616
private readonly disabledVariable = 'POWERTOOLS_METRICS_DISABLED';
1717

1818
/**
@@ -22,6 +22,13 @@ class EnvironmentVariablesService
2222
return this.get(this.namespaceVariable);
2323
}
2424

25+
/**
26+
* Get the value of the `POWERTOOLS_METRICS_FUNCTION_NAME` environment variable.
27+
*/
28+
public getFunctionName(): string {
29+
return this.get(this.functionNameVariable);
30+
}
31+
2532
/**
2633
* Get the value of the `POWERTOOLS_METRICS_DISABLED` or `POWERTOOLS_DEV` environment variables.
2734
*

Diff for: packages/metrics/src/middleware/middy.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ const logMetrics = (
6262

6363
const logMetricsBefore = async (request: MiddyLikeRequest): Promise<void> => {
6464
for (const metrics of metricsInstances) {
65-
metrics.setFunctionName(request.context.functionName);
6665
const { throwOnEmptyMetrics, defaultDimensions, captureColdStartMetric } =
6766
options;
6867
if (throwOnEmptyMetrics) {
@@ -72,7 +71,7 @@ const logMetrics = (
7271
metrics.setDefaultDimensions(defaultDimensions);
7372
}
7473
if (captureColdStartMetric) {
75-
metrics.captureColdStartMetric();
74+
metrics.captureColdStartMetric(request.context.functionName);
7675
}
7776
}
7877

Diff for: packages/metrics/src/types/ConfigServiceInterface.ts

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ interface ConfigServiceInterface extends ConfigServiceBaseInterface {
1212
* Get the value of the `POWERTOOLS_METRICS_NAMESPACE` environment variable.
1313
*/
1414
getNamespace(): string;
15+
/**
16+
* Get the value of the `POWERTOOLS_METRICS_FUNCTION_NAME` environment variable.
17+
*/
18+
getFunctionName(): string;
1519
}
1620

1721
export type { ConfigServiceInterface };

0 commit comments

Comments
 (0)