-
Notifications
You must be signed in to change notification settings - Fork 97
feat(metrics): introduce Metrics.flushMetrics #2154
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
base: main
Are you sure you want to change the base?
Conversation
- introduce `Metrics.flushMetrics` as a more powerful version of `flushSingleMetrics` to allow - using defaults by inheriting state e.g. namespace, dimensions and metadata - emitting multiple metrics in one metrics context - refactor `flushSingleMetrics` to use `flushMetrics` - move namespace/service setting from `MetricsFactory` to `EmfMetricsLogger`
6587c5a
to
13eb9d1
Compare
- introduce `Metrics.flushMetrics` as a more powerful version of `flushSingleMetrics` to allow - using defaults by inheriting state e.g. namespace, dimensions and metadata - emitting multiple metrics in one metrics context - refactor `flushSingleMetrics` to use `flushMetrics` - move namespace/service setting from `MetricsFactory` to `EmfMetricsLogger`
13eb9d1
to
537dc90
Compare
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.
Thanks @humanzz for sending this PR. Overall, it looks good and I left some comments that we need to address before moving forward.
Primarily, can you go back to the issue #2153 and let us know your use-case? We still need to decide whether we want to move forward with inheriting the default configuration of the metrics logger for flushMetrics
and flushSingleMetric
.
powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java
Show resolved
Hide resolved
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
I've addressed the |
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.
Thanks for the quick turnaround @humanzz. Just one more thing that I discovered.
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
...s/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java
Show resolved
Hide resolved
Good catch! It seems that a "property" is simply a key added to the log line while "metadata" becomes part of the Cold start metric (putProperty) {
"_aws": {
"Timestamp": 1751977621635,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Metrics": [
{
"Name": "ColdStart",
"Unit": "Count"
}
],
"Dimensions": [
[
"Service",
"FunctionName"
]
]
}
]
},
"function_request_id": "b8628984-b745-44bb-8025-247c2da76da1",
"xray_trace_id": "1-686d0e92-396456d519ba8c28174120a4",
"ColdStart": 1,
"Service": "payment",
} Regular metric (putMetadata) {
"_aws": {
"Timestamp": 1751977946689,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Metrics": [
{
"Name": "CustomMetric1",
"Unit": "Count"
},
{
"Name": "CustomMetric3",
"Unit": "Count",
"StorageResolution": 1
}
],
"Dimensions": [
[
"Service"
]
]
}
],
"function_request_id": "feccb848-47a9-4b32-a16b-73d45d7ad308",
"xray_trace_id": "1-686d0fdb-651f4fc05b57221e726890c0"
},
"CustomMetric1": 1,
"Service": "payment",
"CustomMetric3": 1
} I need to find out the semantic difference – those nuances don't exist in the other runtimes. None of it is searchable in cloudwatch metrics. Besides the location in the json output I don't see any difference. Update: It appears that putMetadata will add key-value pairs to the We should update the |
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
...trics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java
Outdated
Show resolved
Hide resolved
|
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.
Thanks @humanzz for your continued engagement. Everything looks good so far besides these minor comments. 🚀
The final step after this will be to update the documentation with the new flushMetrics
method including code examples showing developers how to use it. Let me know if you would like to do this – otherwise I am happy to commit the documentation into this PR.
The docs file uses mkdocs and is located here docs/core/metrics.md
.
singleMetricLogger.setNamespace(namespace); | ||
} catch (Exception e) { | ||
LOGGER.error("Namespace cannot be set for single metric due to an error in EMF", e); | ||
// Create a new instance, inheriting namespace/dimensions state |
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.
// Create a new instance, inheriting namespace/dimensions state | |
// Create a new instance, inheriting namespace, default dimensions, and metadata |
LambdaHandlerProcessor.getXrayTraceId() | ||
.ifPresent(traceId -> metricsInstance.addMetadata(TRACE_ID_PROPERTY, traceId)); | ||
Context extractedContext = extractContext(pjp); | ||
MetricsUtils.addRequestIdAndXrayTraceIdIfAvailable(extractedContext, metricsInstance); |
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.
Good catch, the request id was missing here.
|
||
import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; | ||
|
||
class MetricsUtils { |
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.
Can you make this class final
and add a private constructor such as:
private MetricsUtils {
// Utility class
}
?
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.
See Sonarlint finding and pmd analysis.
For classes that only have static methods, consider making them utility classes. Note that this doesn't apply to abstract classes, since their subclasses may well include non-static methods. Also, if you want this class to be a utility class, remember to add a private constructor to prevent instantiation. (Note, that this use was known before PMD 5.1.0 as UseSingleton). UseUtilityClass (Priority: 1, Ruleset: Design) https://docs.pmd-code.org/snapshot/pmd_rules_java_design.html#useutilityclass
* Flush a separate metrics context that inherits the namespace, dimensions and metadata. This creates a separate metrics context | ||
* that doesn't affect the default metrics context. |
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.
* Flush a separate metrics context that inherits the namespace, dimensions and metadata. This creates a separate metrics context | |
* that doesn't affect the default metrics context. | |
* Flush a separate metrics context that inherits the namespace, default dimensions, and metadata. This creates a separate metrics context | |
* that doesn't affect the default metrics context. |
* Flush a separate metrics context that inherits the namespace, dimensions and metadata. This creates a separate metrics context | ||
* that doesn't affect the default metrics context. | ||
* | ||
* @param metricsConsumer the consumer to use to edit the metrics instance (e.g. add metrics, override namespace) before flushing |
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.
* @param metricsConsumer the consumer to use to edit the metrics instance (e.g. add metrics, override namespace) before flushing | |
* @param metricsConsumer the consumer to use to edit the metrics instance (e.g. add metrics, override namespace, add custom dimensions) before flushing |
metrics.setNamespace(namespace); | ||
metrics.addMetric(name, value, unit); | ||
}); | ||
} |
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.
Following the discussion in the issue: All runtimes inherit the namespace by default if it is not overwritten. Let's add the method overload you suggested in your initial feature request here (without namespace param). We should also add a unit test for this.
default void flushSingleMetric(String name, double value, MetricUnit unit) {
flushSingleMetric(name, value, unit, namespace, null);
flushMetrics(metrics -> {
metrics.addMetric(name, value, unit);
});
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.
While this might make sense, a couple of thoughts
- Not sure what value this would provide over
Metrics.addMetric
(I understand it's a different flush, but end result is that the same metric is emitted, reusing namespace, dimensions, metadata) - I sincerely believe that all
flushSingleMetric
should be marked as deprecated, to help reduce the api surface area asflushMetrics
would already enable all that's supported by these overloads
Summary
Changes
Metrics.flushMetrics
as a more powerful version offlushSingleMetrics
to allowEmfMetricsLogger.addMetadata
to use emf'sputProperty
flushSingleMetrics
andcaptureColdStartMetric
to useflushMetrics
MetricsUtils
Issue number: #2153
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.