Skip to content

Commit 4249766

Browse files
committed
Update default dimension and namespace logic to have the precedence: @metrics annotation. MetricsLoggerBuilder, Environment variables.
1 parent 2a79c02 commit 4249766

File tree

6 files changed

+60
-62
lines changed

6 files changed

+60
-62
lines changed

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@
2020
import java.lang.annotation.Target;
2121

2222
/**
23-
* {@code Metrics} is used to signal that the annotated method should be
24-
* extended with Metrics functionality.
23+
* {@code Metrics} is used to signal that the annotated Lambda handler method should be
24+
* extended with Metrics functionality. Will have no effect when used on a method that is not a Lambda handler.
2525
*
2626
* <p>{@code Metrics} allows users to asynchronously create Amazon
2727
* CloudWatch metrics by using the CloudWatch <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html">Embedded Metrics Format</a>.
28-
* {@code Metrics} manages the life-cycle of the MetricsLogger class,
29-
* to simplify the user experience when used with AWS Lambda.
28+
* {@code Metrics} manages the life-cycle and configuration of the MetricsLogger to simplify the user experience when used with AWS Lambda.
3029
*
3130
* <p>{@code Metrics} should be used with the handleRequest method of a class
3231
* which implements either
@@ -64,10 +63,10 @@
6463
String namespace() default "";
6564

6665
String service() default "";
67-
66+
6867
String functionName() default "";
6968

7069
boolean captureColdStart() default false;
7170

7271
boolean raiseOnEmptyMetrics() default false;
73-
}
72+
}

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsLoggerBuilder.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public MetricsLoggerBuilder withNamespace(String namespace) {
6464
}
6565

6666
/**
67-
* Set the service name
67+
* Set the service name. Does not apply if used in combination with default dimensions. If you would like to use a
68+
* service name with default dimensions, use {@link #withDefaultDimension(String, String)} instead.
6869
*
6970
* @param service the service name
7071
* @return this builder
@@ -86,7 +87,7 @@ public MetricsLoggerBuilder withRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics)
8687
}
8788

8889
/**
89-
* Add a default dimension
90+
* Add a default dimension.
9091
*
9192
* @param key the dimension key
9293
* @param value the dimension value
@@ -126,13 +127,13 @@ public MetricsLogger build() {
126127

127128
metricsLogger.setRaiseOnEmptyMetrics(raiseOnEmptyMetrics);
128129

129-
if (!defaultDimensions.isEmpty()) {
130-
metricsLogger.setDefaultDimensions(defaultDimensions);
130+
if (service != null) {
131+
metricsLogger.setDefaultDimensions(Map.of("Service", service));
131132
}
132133

133-
// Add Service dimension separately to ensure it's not mixed with other default dimensions
134-
if (service != null) {
135-
metricsLogger.addDimension("Service", service);
134+
// If the user provided default dimension, we overwrite the default Service dimension again
135+
if (!defaultDimensions.isEmpty()) {
136+
metricsLogger.setDefaultDimensions(defaultDimensions);
136137
}
137138

138139
return metricsLogger;

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsLoggerFactory.java

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414

1515
package software.amazon.lambda.powertools.metrics;
1616

17+
import java.util.Map;
18+
19+
import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor;
1720
import software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider;
1821
import software.amazon.lambda.powertools.metrics.provider.MetricsProvider;
1922

20-
import java.util.HashMap;
21-
import java.util.Map;
22-
2323
/**
2424
* Factory for accessing the singleton MetricsLogger instance
2525
*/
@@ -38,28 +38,19 @@ private MetricsLoggerFactory() {
3838
public static synchronized MetricsLogger getMetricsLogger() {
3939
if (metricsLogger == null) {
4040
metricsLogger = provider.getMetricsLogger();
41-
41+
4242
// Apply default configuration from environment variables
4343
String envNamespace = System.getenv("POWERTOOLS_METRICS_NAMESPACE");
4444
if (envNamespace != null) {
4545
metricsLogger.setNamespace(envNamespace);
4646
}
47-
48-
String envService = System.getenv("POWERTOOLS_SERVICE_NAME");
49-
if (envService != null) {
50-
Map<String, String> dimensions = new HashMap<>();
51-
dimensions.put("Service", envService);
52-
metricsLogger.setDefaultDimensions(dimensions);
53-
} else {
54-
Map<String, String> dimensions = new HashMap<>();
55-
dimensions.put("Service", "service_undefined");
56-
metricsLogger.setDefaultDimensions(dimensions);
57-
}
47+
48+
metricsLogger.setDefaultDimensions(Map.of("Service", LambdaHandlerProcessor.serviceName()));
5849
}
59-
50+
6051
return metricsLogger;
6152
}
62-
53+
6354
/**
6455
* Set the metrics provider
6556
*
@@ -73,4 +64,4 @@ public static synchronized void setMetricsProvider(MetricsProvider metricsProvid
7364
// Reset the logger so it will be recreated with the new provider
7465
metricsLogger = null;
7566
}
76-
}
67+
}

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void setDefaultDimensions(Map<String, String> defaultDimensions) {
9393
// Store a copy of the default dimensions
9494
this.defaultDimensions = new HashMap<>(defaultDimensions);
9595
}
96-
96+
9797
@Override
9898
public software.amazon.lambda.powertools.metrics.model.DimensionSet getDefaultDimensions() {
9999
return software.amazon.lambda.powertools.metrics.model.DimensionSet.of(defaultDimensions);
@@ -268,4 +268,4 @@ private Unit convertUnit(MetricUnit unit) {
268268
return Unit.NONE;
269269
}
270270
}
271-
}
271+
}

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone;
1818
import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.extractContext;
1919
import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isHandlerMethod;
20-
import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName;
2120

22-
import com.amazonaws.services.lambda.runtime.Context;
21+
import java.util.Map;
22+
2323
import org.aspectj.lang.ProceedingJoinPoint;
2424
import org.aspectj.lang.annotation.Around;
2525
import org.aspectj.lang.annotation.Aspect;
2626
import org.aspectj.lang.annotation.Pointcut;
27+
28+
import com.amazonaws.services.lambda.runtime.Context;
29+
2730
import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor;
2831
import software.amazon.lambda.powertools.metrics.Metrics;
2932
import software.amazon.lambda.powertools.metrics.MetricsLogger;
@@ -34,46 +37,49 @@
3437
public class LambdaMetricsAspect {
3538
public static final String TRACE_ID_PROPERTY = "xray_trace_id";
3639
public static final String REQUEST_ID_PROPERTY = "function_request_id";
37-
private static final String NAMESPACE = System.getenv("POWERTOOLS_METRICS_NAMESPACE");
3840

39-
private static String service(Metrics metrics) {
40-
return !"".equals(metrics.service()) ? metrics.service() : serviceName();
41-
}
42-
43-
private String namespace(Metrics metrics) {
44-
return !"".equals(metrics.namespace()) ? metrics.namespace() : NAMESPACE;
45-
}
46-
4741
private String functionName(Metrics metrics, Context context) {
4842
if (!"".equals(metrics.functionName())) {
4943
return metrics.functionName();
5044
}
5145
return context != null ? context.getFunctionName() : null;
5246
}
5347

54-
@SuppressWarnings({"EmptyMethod"})
48+
private String serviceNameWithFallback(Metrics metrics) {
49+
if (!"".equals(metrics.service())) {
50+
return metrics.service();
51+
}
52+
return LambdaHandlerProcessor.serviceName();
53+
}
54+
55+
@SuppressWarnings({ "EmptyMethod" })
5556
@Pointcut("@annotation(metrics)")
5657
public void callAt(Metrics metrics) {
5758
}
5859

5960
@Around(value = "callAt(metrics) && execution(@Metrics * *.*(..))", argNames = "pjp,metrics")
6061
public Object around(ProceedingJoinPoint pjp,
61-
Metrics metrics) throws Throwable {
62+
Metrics metrics) throws Throwable {
6263
Object[] proceedArgs = pjp.getArgs();
6364

6465
if (isHandlerMethod(pjp)) {
6566
MetricsLogger logger = MetricsLoggerFactory.getMetricsLogger();
6667

67-
// Add service dimension separately
68-
logger.addDimension("Service", service(metrics));
68+
// The MetricsLoggerFactory applies default settings from the environment or can be configured by the
69+
// MetricsLoggerBuilder. We only overwrite settings if they are explicitly set in the @Metrics annotation.
70+
if (!"".equals(metrics.namespace())) {
71+
logger.setNamespace(metrics.namespace());
72+
}
6973

70-
// Set namespace
71-
String metricsNamespace = namespace(metrics);
72-
if (metricsNamespace != null) {
73-
logger.setNamespace(metricsNamespace);
74+
// If the default dimensions are larger than 1 or do not contain the "Service" dimension, it means that the
75+
// user overwrote them manually e.g. using MetricsLoggerBuilder. In this case, we don't set the service
76+
// default dimension.
77+
if (!"".equals(metrics.service())
78+
&& logger.getDefaultDimensions().getDimensionKeys().size() <= 1
79+
&& logger.getDefaultDimensions().getDimensionKeys().contains("Service")) {
80+
logger.setDefaultDimensions(Map.of("Service", metrics.service()));
7481
}
7582

76-
// Configure other settings
7783
logger.setRaiseOnEmptyMetrics(metrics.raiseOnEmptyMetrics());
7884

7985
// Add trace ID metadata if available
@@ -84,18 +90,19 @@ public Object around(ProceedingJoinPoint pjp,
8490

8591
if (null != extractedContext) {
8692
logger.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId());
87-
93+
8894
// Only capture cold start metrics if configured
8995
if (metrics.captureColdStart()) {
9096
// Get function name from annotation or context
9197
String funcName = functionName(metrics, extractedContext);
92-
98+
9399
// Create dimensions with service and function name
94100
DimensionSet coldStartDimensions = DimensionSet.of(
95-
"Service", service(metrics),
96-
"FunctionName", funcName != null ? funcName : extractedContext.getFunctionName()
97-
);
98-
101+
"Service",
102+
logger.getDefaultDimensions().getDimensions().getOrDefault("Service",
103+
serviceNameWithFallback(metrics)),
104+
"FunctionName", funcName != null ? funcName : extractedContext.getFunctionName());
105+
99106
logger.captureColdStartMetric(extractedContext, coldStartDimensions);
100107
}
101108
}
@@ -110,4 +117,4 @@ public Object around(ProceedingJoinPoint pjp,
110117

111118
return pjp.proceed(proceedArgs);
112119
}
113-
}
120+
}

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/MetricsProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
* Interface for metrics provider implementations
2121
*/
2222
public interface MetricsProvider {
23-
23+
2424
/**
2525
* Get a new instance of a metrics logger
2626
*
2727
* @return a new metrics logger instance
2828
*/
2929
MetricsLogger getMetricsLogger();
30-
}
30+
}

0 commit comments

Comments
 (0)