Skip to content

feat(metrics): allow setting functionName via constructor parameter and environment variable #3696

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
185e15b
feat(metrics): add ability to pass functionName to middy and decorator
steven10172 Mar 4, 2025
ff79706
docs(metrics): add setting function name section
steven10172 Mar 4, 2025
27875ee
docs(metrics): updated highlighted line for setting function name dec…
steven10172 Mar 4, 2025
68439d6
refactor(metrics): revert setting functionName in middy and decorator…
steven10172 Mar 14, 2025
9efee79
feat(metrics): allow setting functionName via ENV and constructor par…
steven10172 Mar 14, 2025
4de0264
docs(metrics): update docs and mention functionName constructor param…
steven10172 Mar 14, 2025
0a2cec8
Merge branch 'aws-powertools:main' into improv/metrics-no-override-fu…
steven10172 Mar 14, 2025
0616dc5
docs(metrics): add reference to POWERTOOLS_METRICS_FUNCTION_NAME on h…
steven10172 Mar 14, 2025
1c4c25a
refactor(metrics): cleanup code based on sonarqubecloud
steven10172 Mar 14, 2025
2c81643
refactor(metrics): deprecated setFunctionName and expand captureColdS…
steven10172 Mar 19, 2025
1c099b4
docs(metrics): update to become more inline with implementation
steven10172 Mar 19, 2025
61cfd8c
doc updates
steven10172 Mar 19, 2025
55ee400
Merge branch 'aws-powertools:main' into improv/metrics-no-override-fu…
steven10172 Mar 19, 2025
2378cb2
more doc updates
steven10172 Mar 19, 2025
6b008c2
Merge branch 'main' into improv/metrics-no-override-function-name
dreamorosi Mar 20, 2025
f5e5ac0
chore: align with suggested implementation
dreamorosi Mar 20, 2025
21dd0c8
chore: ignore deprecated method from coverage
dreamorosi Mar 20, 2025
29a6280
chore: format table
dreamorosi Mar 20, 2025
d69c2a0
chore: address review comments
dreamorosi Mar 20, 2025
9631937
chore: address sonar
dreamorosi Mar 20, 2025
258becd
Merge branch 'main' into improv/metrics-no-override-function-name
dreamorosi Mar 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions docs/core/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ The library requires two settings. You can set them as environment variables, or

These settings will be used across all metrics emitted:

| Setting | Description | Environment variable | Default | Allowed Values | Example | Constructor parameter |
| -------------------- | ---------------------------------------------------------------- | ------------------------------ | ------------------- | -------------- | ------------------- | --------------------- |
| **Service** | Optionally, sets **service** metric dimension across all metrics | `POWERTOOLS_SERVICE_NAME` | `service_undefined` | Any string | `serverlessAirline` | `serviceName` |
| **Metric namespace** | Logical container where all metrics will be placed | `POWERTOOLS_METRICS_NAMESPACE` | `default_namespace` | Any string | `serverlessAirline` | `default_namespace` |
| **Enabled** | Whether to emit metrics to standard output or not | `POWERTOOLS_METRICS_ENABLED` | `true` | Boolean | `false` | |
| Setting | Description | Environment variable | Default | Allowed Values | Example | Constructor parameter |
|----------------------|------------------------------------------------------------------|------------------------------------|----------------------------------------------------------|----------------|---------------------|-----------------------|
| **Service** | Optionally, sets **service** metric dimension across all metrics | `POWERTOOLS_SERVICE_NAME` | `service_undefined` | Any string | `serverlessAirline` | `serviceName` |
| **Metric namespace** | Logical container where all metrics will be placed | `POWERTOOLS_METRICS_NAMESPACE` | `default_namespace` | Any string | `serverlessAirline` | `default_namespace` |
| **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` |
| **Enabled** | Whether to emit metrics to standard output or not | `POWERTOOLS_METRICS_ENABLED` | `true` | Boolean | `false` | |

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

=== "template.yml"

```yaml hl_lines="9 10"
```yaml hl_lines="8-10"
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Expand All @@ -97,6 +98,7 @@ The `Metrics` utility is instantiated outside of the Lambda handler. In doing th
Variables:
POWERTOOLS_SERVICE_NAME: orders
POWERTOOLS_METRICS_NAMESPACE: serverlessAirline
POWERTOOLS_METRICS_FUNCTION_NAME: my-function-name
```

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

### Adding default dimensions

You can add default dimensions to your metrics by passing them as parameters in 4 ways:
You can add default dimensions to your metrics by passing them as parameters in 4 ways:

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

!!! 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."

#### Setting function name

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`.

The priority of the `function_name` dimension value is defined as:

1. `functionName` constructor option
2. `POWERTOOLS_METRICS_FUNCTION_NAME` environment variable
3. The value passed in the `captureColdStartMetric` call, or `context.functionName` if using logMetrics decorator or Middy middleware

=== "constructor"

```typescript hl_lines="6"
--8<-- "examples/snippets/metrics/functionName.ts"
```

=== "captureColdStartMetric method"

```typescript hl_lines="12"
--8<-- "examples/snippets/metrics/captureColdStartMetric.ts"
```

## Advanced

### Adding metadata
Expand Down
33 changes: 17 additions & 16 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,22 +351,23 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al
???+ info
Explicit parameters take precedence over environment variables

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

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

Expand Down
17 changes: 17 additions & 0 deletions examples/snippets/metrics/captureColdStartMetric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MetricUnit, Metrics } from '@aws-lambda-powertools/metrics';

const metrics = new Metrics({
namespace: 'serverlessAirline',
serviceName: 'orders',
});

export const handler = async (
_event: unknown,
_context: unknown
): Promise<void> => {
metrics.captureColdStartMetric('my-function-name');

metrics.addMetric('successfulBooking', MetricUnit.Count, 1);

metrics.publishStoredMetrics();
};
18 changes: 18 additions & 0 deletions examples/snippets/metrics/functionName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { MetricUnit, Metrics } from '@aws-lambda-powertools/metrics';

const metrics = new Metrics({
namespace: 'serverlessAirline',
serviceName: 'orders',
functionName: 'my-function-name',
});

export const handler = async (
_event: unknown,
_context: unknown
): Promise<void> => {
metrics.captureColdStartMetric();

metrics.addMetric('successfulBooking', MetricUnit.Count, 1);

metrics.publishStoredMetrics();
};
55 changes: 30 additions & 25 deletions packages/metrics/src/Metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,10 @@ class Metrics extends Utility implements MetricsInterface {
* metrics.captureColdStartMetric();
* };
* ```
*
* @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.
*/
public captureColdStartMetric(): void {
public captureColdStartMetric(functionName?: string): void {
if (!this.getColdStart()) return;
const singleMetric = this.singleMetric();

Expand All @@ -381,8 +383,9 @@ class Metrics extends Utility implements MetricsInterface {
service: this.defaultDimensions.service,
});
}
if (this.functionName != null) {
singleMetric.addDimension('function_name', this.functionName);
const value = this.functionName?.trim() ?? functionName?.trim();
if (value && value.length > 0) {
singleMetric.addDimension('function_name', value);
}
singleMetric.addMetric(COLD_START_METRIC, MetricUnits.Count, 1);
}
Expand Down Expand Up @@ -543,8 +546,9 @@ class Metrics extends Utility implements MetricsInterface {
context: Context,
callback: Callback
): Promise<unknown> {
metricsRef.functionName = context.functionName;
if (captureColdStartMetric) metricsRef.captureColdStartMetric();
if (captureColdStartMetric) {
metricsRef.captureColdStartMetric(context.functionName);
}

let result: unknown;
try {
Expand Down Expand Up @@ -749,28 +753,14 @@ class Metrics extends Utility implements MetricsInterface {
}

/**
* Set the function name to be added to each metric as a dimension.
*
* When using the {@link Metrics.logMetrics | `logMetrics()`} decorator, or the Middy.js middleware, the function
* name is automatically inferred from the Lambda context.
*
* @example
* ```typescript
* import { Metrics } from '@aws-lambda-powertools/metrics';
*
* const metrics = new Metrics({
* namespace: 'serverlessAirline',
* serviceName: 'orders'
* });
*
* metrics.setFunctionName('my-function-name');
* ```
*
* @param name - The function name
* @deprecated Override the function name for `ColdStart` metrics inferred from the context either via:
* - `functionName` constructor parameter
* - `POWERTOOLS_FUNCTION_NAME` environment variable
* - {@link Metrics.captureColdStartMetric | `captureColdStartMetric('myFunctionName')`} method
*/
public setFunctionName(name: string): void {
/* v8 ignore start */ public setFunctionName(name: string): void {
this.functionName = name;
}
} /* v8 ignore end */

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

/**
* Set the function name for the cold start metric.
*
* @param functionName - The function name to be used for the cold start metric set in the constructor
*/
protected setFunctionNameForColdStartMetric(functionName?: string): void {
const value =
functionName?.trim() ?? this.getEnvVarsService().getFunctionName().trim();
if (value && value.length > 0) {
this.functionName = value;
}
}

/**
* Set the namespace to be used.
*
Expand Down Expand Up @@ -951,6 +954,7 @@ class Metrics extends Utility implements MetricsInterface {
serviceName,
singleMetric,
defaultDimensions,
functionName,
} = options;

this.setEnvVarsService();
Expand All @@ -960,6 +964,7 @@ class Metrics extends Utility implements MetricsInterface {
this.setNamespace(namespace);
this.setService(serviceName);
this.setDefaultDimensions(defaultDimensions);
this.setFunctionNameForColdStartMetric(functionName);
this.isSingleMetric = singleMetric || false;

return this;
Expand Down
11 changes: 9 additions & 2 deletions packages/metrics/src/config/EnvironmentVariablesService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class EnvironmentVariablesService
extends CommonEnvironmentVariablesService
implements ConfigServiceInterface
{
private namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE';

private readonly namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE';
private readonly functionNameVariable = 'POWERTOOLS_METRICS_FUNCTION_NAME';
private readonly disabledVariable = 'POWERTOOLS_METRICS_DISABLED';

/**
Expand All @@ -22,6 +22,13 @@ class EnvironmentVariablesService
return this.get(this.namespaceVariable);
}

/**
* Get the value of the `POWERTOOLS_METRICS_FUNCTION_NAME` environment variable.
*/
public getFunctionName(): string {
return this.get(this.functionNameVariable);
}

/**
* Get the value of the `POWERTOOLS_METRICS_DISABLED` or `POWERTOOLS_DEV` environment variables.
*
Expand Down
3 changes: 1 addition & 2 deletions packages/metrics/src/middleware/middy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ const logMetrics = (

const logMetricsBefore = async (request: MiddyLikeRequest): Promise<void> => {
for (const metrics of metricsInstances) {
metrics.setFunctionName(request.context.functionName);
const { throwOnEmptyMetrics, defaultDimensions, captureColdStartMetric } =
options;
if (throwOnEmptyMetrics) {
Expand All @@ -72,7 +71,7 @@ const logMetrics = (
metrics.setDefaultDimensions(defaultDimensions);
}
if (captureColdStartMetric) {
metrics.captureColdStartMetric();
metrics.captureColdStartMetric(request.context.functionName);
}
}

Expand Down
4 changes: 4 additions & 0 deletions packages/metrics/src/types/ConfigServiceInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ interface ConfigServiceInterface extends ConfigServiceBaseInterface {
* Get the value of the `POWERTOOLS_METRICS_NAMESPACE` environment variable.
*/
getNamespace(): string;
/**
* Get the value of the `POWERTOOLS_METRICS_FUNCTION_NAME` environment variable.
*/
getFunctionName(): string;
}

export type { ConfigServiceInterface };
Loading