diff --git a/pom.xml b/pom.xml
index 293ec00..4bd6257 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,6 +86,7 @@
1.2.3
3.11.6
2.26.4
+ 4.2.0
1.12.667
1.12.745
0.9.6
@@ -303,6 +304,11 @@
aws-lambda-java-core
${version.lambda-core}
+
+ software.amazon.cloudwatchlogs
+ aws-embedded-metrics
+ ${version.aws-metrics}
+
com.amazonaws
aws-java-sdk-dynamodb
diff --git a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/APMMetricsMiddleware.java b/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/APMMetricsMiddleware.java
deleted file mode 100644
index 43522ca..0000000
--- a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/APMMetricsMiddleware.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package com.networknt.aws.lambda.handler.middleware.metrics;
-
-import com.networknt.aws.lambda.LightLambdaExchange;
-import com.networknt.aws.lambda.app.LambdaAppConfig;
-import com.networknt.config.Config;
-import com.networknt.config.JsonMapper;
-import com.networknt.metrics.APMAgentReporter;
-import com.networknt.metrics.MetricsConfig;
-import com.networknt.metrics.TimeSeriesDbSender;
-import com.networknt.status.Status;
-import com.networknt.utility.Constants;
-import com.networknt.utility.ModuleRegistry;
-import io.dropwizard.metrics.Clock;
-import io.dropwizard.metrics.MetricFilter;
-import io.dropwizard.metrics.MetricName;
-import io.dropwizard.metrics.MetricRegistry;
-import io.dropwizard.metrics.broadcom.APMEPAgentSender;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.MalformedURLException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.networknt.aws.lambda.handler.middleware.audit.AuditMiddleware.AUDIT_ATTACHMENT_KEY;
-
-public class APMMetricsMiddleware extends AbstractMetricsMiddleware {
- static final Logger logger = LoggerFactory.getLogger(APMMetricsMiddleware.class);
- public static final LambdaAppConfig LAMBDA_APP_CONFIG = (LambdaAppConfig) Config.getInstance().getJsonObjectConfig(LambdaAppConfig.CONFIG_NAME, LambdaAppConfig.class);
- // this is the indicator to start the reporter and construct the common tags. It cannot be static as
- // the currentPort and currentAddress are not available during the handler initialization.
- private boolean firstTime = true;
- private long startTime;
-
- public APMMetricsMiddleware() {
- config = MetricsConfig.load();
- if(config.getIssuerRegex() != null) {
- pattern = Pattern.compile(config.getIssuerRegex());
- }
- ModuleRegistry.registerModule(MetricsConfig.CONFIG_NAME, APMMetricsMiddleware.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(MetricsConfig.CONFIG_NAME), null);
- if(logger.isDebugEnabled()) logger.debug("ApmMetricsMiddleware is constructed!");
- }
-
- @Override
- public Status execute(LightLambdaExchange exchange) {
- if (firstTime) {
- commonTags.put("api", LAMBDA_APP_CONFIG.getLambdaAppId());
-// commonTags.put("env", );
-// commonTags.put("addr", Server.currentAddress);
-// commonTags.put("port", "" + (ServerConfig.getInstance().isEnableHttps() ? Server.currentHttpsPort : Server.currentHttpPort));
-// InetAddress inetAddress = Util.getInetAddress();
-// commonTags.put("host", inetAddress == null ? "unknown" : inetAddress.getHostName()); // will be container id if in docker.
- if (logger.isDebugEnabled()) {
- logger.debug(commonTags.toString());
- }
-
- try {
- TimeSeriesDbSender sender =
- new APMEPAgentSender(config.getServerProtocol(), config.getServerHost(), config.getServerPort(), config.getServerPath(), LAMBDA_APP_CONFIG.getLambdaAppId(), config.getProductName());
- APMAgentReporter reporter = APMAgentReporter
- .forRegistry(registry)
- .convertRatesTo(TimeUnit.SECONDS)
- .convertDurationsTo(TimeUnit.MILLISECONDS)
- .filter(MetricFilter.ALL)
- .build(sender);
- reporter.start(config.getReportInMinutes(), TimeUnit.MINUTES);
-
- logger.info("apmmetrics is enabled and reporter is started");
- } catch (MalformedURLException e) {
- logger.error("apmmetrics has failed to initialize APMEPAgentSender", e);
- }
-
- // reset the flag so that this block will only be called once.
- firstTime = false;
- }
-
- if(exchange.isRequestInProgress()) {
- startTime = Clock.defaultClock().getTick();
- }
-
- exchange.addResponseCompleteListener(finalExchange -> {
- Map auditInfo = (Map)finalExchange.getAttachment(AUDIT_ATTACHMENT_KEY);
- if(logger.isTraceEnabled()) logger.trace("auditInfo = {}", auditInfo);
- if (auditInfo != null && !auditInfo.isEmpty()) {
- Map tags = new HashMap<>();
- tags.put("endpoint", (String) auditInfo.get(Constants.ENDPOINT_STRING));
- String clientId = auditInfo.get(Constants.CLIENT_ID_STRING) != null ? (String) auditInfo.get(Constants.CLIENT_ID_STRING) : "unknown";
- if(logger.isTraceEnabled()) logger.trace("clientId = {}", clientId);
- tags.put("clientId", clientId);
- // scope client id will only be available if two token is used. For example, authorization code flow.
- if (config.isSendScopeClientId()) {
- tags.put("scopeClientId", auditInfo.get(Constants.SCOPE_CLIENT_ID_STRING) != null ? (String) auditInfo.get(Constants.SCOPE_CLIENT_ID_STRING) : "unknown");
- }
- // caller id is the calling serviceId that is passed from the caller. It is not always available but some organizations enforce it.
- if (config.isSendCallerId()) {
- tags.put("callerId", auditInfo.get(Constants.CALLER_ID_STRING) != null ? (String) auditInfo.get(Constants.CALLER_ID_STRING) : "unknown");
- }
- if (config.isSendIssuer()) {
- String issuer = (String) auditInfo.get(Constants.ISSUER_CLAIMS);
- if (issuer != null) {
- // we need to send issuer as a tag. Do we need to apply regex to extract only a part of the issuer?
- if(config.getIssuerRegex() != null) {
- Matcher matcher = pattern.matcher(issuer);
- if (matcher.find()) {
- String iss = matcher.group(1);
- if(logger.isTraceEnabled()) logger.trace("Extracted issuer {} from Original issuer {] is sent.", iss, issuer);
- tags.put("issuer", iss != null ? iss : "unknown");
- }
- } else {
- if(logger.isTraceEnabled()) logger.trace("Original issuer {} is sent.", issuer);
- tags.put("issuer", issuer);
- }
- }
- }
- MetricName metricName = new MetricName("response_time");
- metricName = metricName.tagged(commonTags);
- metricName = metricName.tagged(tags);
- long time = Clock.defaultClock().getTick() - startTime;
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.TIMERS).update(time, TimeUnit.NANOSECONDS);
- if(logger.isTraceEnabled())
- logger.trace("metricName = {} commonTags = {} tags = {}", metricName, JsonMapper.toJson(commonTags), JsonMapper.toJson(tags));
- incCounterForStatusCode(finalExchange.getFinalizedResponse(true).getStatusCode(), commonTags, tags);
- } else {
- // when we reach here, it will be in light-gateway so no specification is loaded on the server and also the security verification is failed.
- // we need to come up with the endpoint at last to ensure we have some meaningful metrics info populated.
- logger.error("auditInfo is null or empty. Please move the path prefix handler to the top of the handler chain after metrics.");
- }
- });
- return successMiddlewareStatus();
- }
-
- @Override
- public void register() {
- ModuleRegistry.registerModule(
- MetricsConfig.CONFIG_NAME,
- APMMetricsMiddleware.class.getName(),
- Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(MetricsConfig.CONFIG_NAME),
- null
- );
-
- }
-
- @Override
- public void reload() {
-
- }
-
- @Override
- public boolean isAsynchronous() {
- return false;
- }
-
- @Override
- public boolean isContinueOnFailure() {
- return false;
- }
-
- @Override
- public boolean isAudited() {
- return false;
- }
-
- @Override
- public void getCachedConfigurations() {
-
- }
-}
diff --git a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/AbstractMetricsMiddleware.java b/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/AbstractMetricsMiddleware.java
index 376f151..04972ed 100644
--- a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/AbstractMetricsMiddleware.java
+++ b/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/AbstractMetricsMiddleware.java
@@ -2,17 +2,22 @@
import com.networknt.aws.lambda.handler.MiddlewareHandler;
import com.networknt.aws.lambda.LightLambdaExchange;
+import com.networknt.aws.lambda.handler.middleware.audit.AuditMiddleware;
import com.networknt.config.JsonMapper;
import com.networknt.metrics.JVMMetricsDbReporter;
import com.networknt.metrics.MetricsConfig;
import com.networknt.metrics.TimeSeriesDbSender;
import com.networknt.status.Status;
import com.networknt.utility.Constants;
+import io.dropwizard.metrics.Metric;
import io.dropwizard.metrics.MetricFilter;
import io.dropwizard.metrics.MetricName;
import io.dropwizard.metrics.MetricRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
+import software.amazon.cloudwatchlogs.emf.model.MetricsContext;
+import software.amazon.cloudwatchlogs.emf.model.Unit;
import java.util.HashMap;
import java.util.Map;
@@ -24,43 +29,28 @@
public abstract class AbstractMetricsMiddleware implements MiddlewareHandler {
static final Logger logger = LoggerFactory.getLogger(AbstractMetricsMiddleware.class);
+ public static final LightLambdaExchange.Attachable METRICS_LOGGER_ATTACHMENT_KEY = LightLambdaExchange.Attachable.createAttachable(AbstractMetricsMiddleware.class);
// The metrics.yml configuration that supports reload.
public static MetricsConfig config;
- static Pattern pattern;
- // The structure that collect all the metrics entries. Even others will be using this structure to inject.
- public static final MetricRegistry registry = new MetricRegistry();
- public Map commonTags = new HashMap<>();
public AbstractMetricsMiddleware() {
}
-
@Override
public boolean isEnabled() {
return config.isEnabled();
}
- public void createJVMMetricsReporter(final TimeSeriesDbSender sender) {
- JVMMetricsDbReporter jvmReporter = new JVMMetricsDbReporter(new MetricRegistry(), sender, "jvm-reporter",
- MetricFilter.ALL, TimeUnit.SECONDS, TimeUnit.MILLISECONDS, commonTags);
- jvmReporter.start(config.getReportInMinutes(), TimeUnit.MINUTES);
- }
-
- public void incCounterForStatusCode(int statusCode, Map commonTags, Map tags) {
- MetricName metricName = new MetricName("request").tagged(commonTags).tagged(tags);
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.COUNTERS).inc();
+ public void incCounterForStatusCode(MetricsLogger metricsLogger, int statusCode) {
+ metricsLogger.putMetric("request", 1, Unit.COUNT);
if (statusCode >= 200 && statusCode < 400) {
- metricName = new MetricName("success").tagged(commonTags).tagged(tags);
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.COUNTERS).inc();
+ metricsLogger.putMetric("success", 1, Unit.COUNT);
} else if (statusCode == 401 || statusCode == 403) {
- metricName = new MetricName("auth_error").tagged(commonTags).tagged(tags);
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.COUNTERS).inc();
+ metricsLogger.putMetric("auth_error", 1, Unit.COUNT);
} else if (statusCode >= 400 && statusCode < 500) {
- metricName = new MetricName("request_error").tagged(commonTags).tagged(tags);
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.COUNTERS).inc();
+ metricsLogger.putMetric("request_error", 1, Unit.COUNT);
} else if (statusCode >= 500) {
- metricName = new MetricName("server_error").tagged(commonTags).tagged(tags);
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.COUNTERS).inc();
+ metricsLogger.putMetric("server_error", 1, Unit.COUNT);
}
}
@@ -70,69 +60,17 @@ public void incCounterForStatusCode(int statusCode, Map commonTa
* @param exchange the LightLambdaExchange that is used to get the auditInfo to collect the metrics tag.
* @param startTime the start time passed in to calculate the response time.
* @param metricsName the name of the metrics that is collected.
- * @param endpoint the endpoint that is used to collect the metrics. It is optional and only provided by the external handlers.
*/
- public void injectMetrics(LightLambdaExchange exchange, long startTime, String metricsName, String endpoint) {
- Map auditInfo = (Map)exchange.getAttachment(AUDIT_ATTACHMENT_KEY);
- if(logger.isTraceEnabled()) logger.trace("auditInfo = " + auditInfo);
- Map tags = new HashMap<>();
- if (auditInfo != null) {
- // for external handlers, the endpoint must be unknown in the auditInfo. If that is the case, use the endpoint passed in.
- if (endpoint != null) {
- tags.put(Constants.ENDPOINT_STRING, endpoint);
- } else {
- tags.put(Constants.ENDPOINT_STRING, (String) auditInfo.get(Constants.ENDPOINT_STRING));
- }
- String clientId = auditInfo.get(Constants.CLIENT_ID_STRING) != null ? (String) auditInfo.get(Constants.CLIENT_ID_STRING) : "unknown";
- if(logger.isTraceEnabled()) logger.trace("clientId = {}", clientId);
- tags.put("clientId", clientId);
- // scope client id will only be available if two token is used. For example, authorization code flow.
- if (config.isSendScopeClientId()) {
- tags.put("scopeClientId", auditInfo.get(Constants.SCOPE_CLIENT_ID_STRING) != null ? (String) auditInfo.get(Constants.SCOPE_CLIENT_ID_STRING) : "unknown");
- }
- // caller id is the calling serviceId that is passed from the caller. It is not always available but some organizations enforce it.
- if (config.isSendCallerId()) {
- tags.put("callerId", auditInfo.get(Constants.CALLER_ID_STRING) != null ? (String) auditInfo.get(Constants.CALLER_ID_STRING) : "unknown");
- }
- if (config.isSendIssuer()) {
- String issuer = (String) auditInfo.get(Constants.ISSUER_CLAIMS);
- if (issuer != null) {
- // we need to send issuer as a tag. Do we need to apply regex to extract only a part of the issuer?
- if(config.getIssuerRegex() != null) {
- Matcher matcher = pattern.matcher(issuer);
- if (matcher.find()) {
- String iss = matcher.group(1);
- if(logger.isTraceEnabled()) logger.trace("Extracted issuer {} from Original issuer {] is sent.", iss, issuer);
- tags.put("issuer", iss != null ? iss : "unknown");
- }
- } else {
- if(logger.isTraceEnabled()) logger.trace("Original issuer {} is sent.", issuer);
- tags.put("issuer", issuer);
- }
- }
- }
- } else {
- // for MRAS and Salesforce handlers that do not have auditInfo in the exchange as they may be called anonymously.
- tags.put(Constants.ENDPOINT_STRING, endpoint == null ? "unknown" : endpoint);
- tags.put("clientId", "unknown");
- if (config.isSendScopeClientId()) {
- tags.put("scopeClientId", "unknown");
- }
- if (config.isSendCallerId()) {
- tags.put("callerId", "unknown");
- }
- if (config.isSendIssuer()) {
- tags.put("issuer", "unknown");
- }
+ public void injectMetrics(LightLambdaExchange exchange, long startTime, String metricsName) {
+ MetricsLogger metricsLogger = (exchange.getAttachment(METRICS_LOGGER_ATTACHMENT_KEY) != null) ? (MetricsLogger) exchange.getAttachment(METRICS_LOGGER_ATTACHMENT_KEY) : null;
+ if(metricsLogger == null) {
+ if(logger.isTraceEnabled()) logger.trace("metricsContext is null, create one.");
+ metricsLogger = new MetricsLogger();
+ exchange.addAttachment(METRICS_LOGGER_ATTACHMENT_KEY, metricsLogger);
}
- MetricName metricName = new MetricName(metricsName);
- metricName = metricName.tagged(commonTags);
- metricName = metricName.tagged(tags);
- long time = System.nanoTime() - startTime;
- registry.getOrAdd(metricName, MetricRegistry.MetricBuilder.TIMERS).update(time, TimeUnit.NANOSECONDS);
+ long time = System.currentTimeMillis() - startTime;
+ metricsLogger.putMetric(metricsName, time, Unit.MILLISECONDS);
if(logger.isTraceEnabled())
- logger.trace("metricName = {} commonTags = {} tags = {}", metricName, JsonMapper.toJson(commonTags), JsonMapper.toJson(tags));
- // the metrics handler will collect the status code metrics and increase the counter. Here we don't want to increase it again.
- // incCounterForStatusCode(httpServerExchange.getStatusCode(), commonTags, tags);
+ logger.trace("metricName {} is injected with time {}", metricsName, time);
}
}
diff --git a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/CloudWatchMetricsMiddleware.java b/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/CloudWatchMetricsMiddleware.java
new file mode 100644
index 0000000..e427338
--- /dev/null
+++ b/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/CloudWatchMetricsMiddleware.java
@@ -0,0 +1,152 @@
+package com.networknt.aws.lambda.handler.middleware.metrics;
+
+import com.networknt.aws.lambda.LightLambdaExchange;
+import com.networknt.aws.lambda.app.LambdaAppConfig;
+import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
+import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
+import software.amazon.cloudwatchlogs.emf.model.Unit;
+import com.networknt.config.Config;
+import com.networknt.metrics.MetricsConfig;
+import com.networknt.status.Status;
+import com.networknt.utility.Constants;
+import com.networknt.utility.ModuleRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static com.networknt.aws.lambda.handler.middleware.audit.AuditMiddleware.AUDIT_ATTACHMENT_KEY;
+
+public class CloudWatchMetricsMiddleware extends AbstractMetricsMiddleware {
+ static final Logger logger = LoggerFactory.getLogger(CloudWatchMetricsMiddleware.class);
+ public static final LambdaAppConfig LAMBDA_APP_CONFIG = (LambdaAppConfig) Config.getInstance().getJsonObjectConfig(LambdaAppConfig.CONFIG_NAME, LambdaAppConfig.class);
+ static Pattern pattern;
+ private long startTime;
+
+ public CloudWatchMetricsMiddleware() {
+ config = MetricsConfig.load();
+ if(config.getIssuerRegex() != null) {
+ pattern = Pattern.compile(config.getIssuerRegex());
+ }
+ ModuleRegistry.registerModule(MetricsConfig.CONFIG_NAME, CloudWatchMetricsMiddleware.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(MetricsConfig.CONFIG_NAME), null);
+ if(logger.isDebugEnabled()) logger.debug("CloudWatchMetricsMiddleware is constructed!");
+
+ }
+
+ @Override
+ public Status execute(LightLambdaExchange exchange) {
+ if(exchange.isRequestInProgress()) {
+ // this is in the request chain time.
+ startTime = System.currentTimeMillis();
+ }
+
+ exchange.addResponseCompleteListener(finalExchange -> {
+ MetricsLogger metricsLogger = (exchange.getAttachment(METRICS_LOGGER_ATTACHMENT_KEY) != null) ? (MetricsLogger) exchange.getAttachment(METRICS_LOGGER_ATTACHMENT_KEY) : null;
+ if(metricsLogger == null) {
+ if(logger.isTraceEnabled()) logger.trace("metricsLogger is null, create one.");
+ metricsLogger = new MetricsLogger();
+ exchange.addAttachment(METRICS_LOGGER_ATTACHMENT_KEY, metricsLogger);
+ }
+
+ // this is in the response chain.
+ Map auditInfo = (Map)finalExchange.getAttachment(AUDIT_ATTACHMENT_KEY);
+ if(logger.isTraceEnabled()) logger.trace("auditInfo = {}", auditInfo);
+ if (auditInfo != null && !auditInfo.isEmpty()) {
+ Map tags = new HashMap<>();
+ metricsLogger.putProperty("endpoint", auditInfo.get(Constants.ENDPOINT_STRING));
+ String clientId = auditInfo.get(Constants.CLIENT_ID_STRING) != null ? (String) auditInfo.get(Constants.CLIENT_ID_STRING) : "unknown";
+ if (logger.isTraceEnabled()) logger.trace("clientId = {}", clientId);
+ metricsLogger.putProperty("clientId", clientId);
+ // scope client id will only be available if two token is used. For example, authorization code flow.
+ if (config.isSendScopeClientId()) {
+ metricsLogger.putProperty("scopeClientId", auditInfo.get(Constants.SCOPE_CLIENT_ID_STRING) != null ? auditInfo.get(Constants.SCOPE_CLIENT_ID_STRING) : "unknown");
+ }
+ // caller id is the calling serviceId that is passed from the caller. It is not always available but some organizations enforce it.
+ if (config.isSendCallerId()) {
+ metricsLogger.putProperty("callerId", auditInfo.get(Constants.CALLER_ID_STRING) != null ? auditInfo.get(Constants.CALLER_ID_STRING) : "unknown");
+ }
+ if (config.isSendIssuer()) {
+ String issuer = (String) auditInfo.get(Constants.ISSUER_CLAIMS);
+ if (issuer != null) {
+ // we need to send issuer as a tag. Do we need to apply regex to extract only a part of the issuer?
+ if (config.getIssuerRegex() != null) {
+ Matcher matcher = pattern.matcher(issuer);
+ if (matcher.find()) {
+ String iss = matcher.group(1);
+ if (logger.isTraceEnabled())
+ logger.trace("Extracted issuer {} from Original issuer {} is sent.", iss, issuer);
+ metricsLogger.putProperty("issuer", iss != null ? iss : "unknown");
+ }
+ } else {
+ if (logger.isTraceEnabled()) logger.trace("Original issuer {} is sent.", issuer);
+ metricsLogger.putProperty("issuer", issuer);
+ }
+ }
+ }
+ } else {
+ // when we reach here, it will be in an instance without specification is loaded on the server and also
+ // the security verification is failed or disabled.
+ // we need to come up with the endpoint at last to ensure we have some meaningful metrics info populated.
+ metricsLogger.putProperty(Constants.ENDPOINT_STRING, "unknown");
+ metricsLogger.putProperty("clientId", "unknown");
+ if (config.isSendScopeClientId()) {
+ metricsLogger.putProperty("scopeClientId", "unknown");
+ }
+ if (config.isSendCallerId()) {
+ metricsLogger.putProperty("callerId", "unknown");
+ }
+ if (config.isSendIssuer()) {
+ metricsLogger.putProperty("issuer", "unknown");
+ }
+ logger.error("auditInfo is null or empty. Please move the path prefix handler to the top of the handler chain after metrics.");
+ }
+
+ long time = System.currentTimeMillis() - startTime;
+ metricsLogger.putMetric("response_time", time, Unit.MILLISECONDS);
+ incCounterForStatusCode(metricsLogger, finalExchange.getFinalizedResponse(true).getStatusCode());
+ metricsLogger.putDimensions(DimensionSet.of("Service", "Aggregator"));
+ metricsLogger.putProperty("api", LAMBDA_APP_CONFIG.getLambdaAppId());
+ metricsLogger.flush();
+ });
+ return successMiddlewareStatus();
+ }
+
+ @Override
+ public boolean isContinueOnFailure() {
+ return false;
+ }
+
+ @Override
+ public boolean isAudited() {
+ return false;
+ }
+
+ @Override
+ public void getCachedConfigurations() {
+
+ }
+
+ @Override
+ public void register() {
+ ModuleRegistry.registerModule(
+ MetricsConfig.CONFIG_NAME,
+ CloudWatchMetricsMiddleware.class.getName(),
+ Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(MetricsConfig.CONFIG_NAME),
+ null
+ );
+
+ }
+
+ @Override
+ public void reload() {
+
+ }
+
+ @Override
+ public boolean isAsynchronous() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/InfluxMetricsMiddleware.java b/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/InfluxMetricsMiddleware.java
deleted file mode 100644
index d431f36..0000000
--- a/src/main/java/com/networknt/aws/lambda/handler/middleware/metrics/InfluxMetricsMiddleware.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.networknt.aws.lambda.handler.middleware.metrics;
-
-import com.networknt.aws.lambda.LightLambdaExchange;
-import com.networknt.status.Status;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class InfluxMetricsMiddleware extends AbstractMetricsMiddleware {
- private static final Logger LOG = LoggerFactory.getLogger(InfluxMetricsMiddleware.class);
-
- @Override
- public Status execute(LightLambdaExchange exchange) {
- if(LOG.isDebugEnabled()) LOG.debug("InfluxMetricsMiddleware.execute starts.");
- return null;
- }
-
- @Override
- public void register() {
-
- }
-
- @Override
- public void reload() {
-
- }
-
- @Override
- public boolean isAsynchronous() {
- return false;
- }
-
- @Override
- public boolean isContinueOnFailure() {
- return false;
- }
-
- @Override
- public boolean isAudited() {
- return false;
- }
-
- @Override
- public void getCachedConfigurations() {
-
- }
-}
diff --git a/src/main/java/com/networknt/aws/lambda/handler/middleware/proxy/LambdaProxyMiddleware.java b/src/main/java/com/networknt/aws/lambda/handler/middleware/proxy/LambdaProxyMiddleware.java
index 8154e91..b301560 100644
--- a/src/main/java/com/networknt/aws/lambda/handler/middleware/proxy/LambdaProxyMiddleware.java
+++ b/src/main/java/com/networknt/aws/lambda/handler/middleware/proxy/LambdaProxyMiddleware.java
@@ -116,14 +116,14 @@ private String invokeFunction(final LambdaAsyncClient client, String functionNam
.logType(CONFIG.getLogType())
.payload(payload)
.build();
- long startTime = System.nanoTime();
+ long startTime = System.currentTimeMillis();
CompletableFuture futureResponse = client.invoke(request)
.thenApply(res -> {
if(CONFIG.isMetricsInjection()) {
if(metricsMiddleware == null) lookupMetricsMiddleware();
if(metricsMiddleware != null) {
if (LOG.isTraceEnabled()) LOG.trace("Inject metrics for {}", CONFIG.getMetricsName());
- metricsMiddleware.injectMetrics(exchange, startTime, CONFIG.getMetricsName(), null);
+ metricsMiddleware.injectMetrics(exchange, startTime, CONFIG.getMetricsName());
}
}
if (LOG.isTraceEnabled()) LOG.trace("LambdaProxyMiddleware.invokeFunction response: {}", res);
diff --git a/src/main/java/com/networknt/aws/lambda/handler/middleware/router/LambdaRouterMiddleware.java b/src/main/java/com/networknt/aws/lambda/handler/middleware/router/LambdaRouterMiddleware.java
index 6148e35..33a0171 100644
--- a/src/main/java/com/networknt/aws/lambda/handler/middleware/router/LambdaRouterMiddleware.java
+++ b/src/main/java/com/networknt/aws/lambda/handler/middleware/router/LambdaRouterMiddleware.java
@@ -88,7 +88,7 @@ public Status execute(LightLambdaExchange exchange) {
}
if(LOG.isTraceEnabled()) LOG.trace("Discovered host {} for ServiceId {}", host, serviceId);
// call the downstream service based on the request methods.
- long startTime = System.nanoTime();
+ long startTime = System.currentTimeMillis();
if("get".equalsIgnoreCase(method) || "delete".equalsIgnoreCase(method)) {
HttpClientRequest request = new HttpClientRequest();
try {
@@ -104,7 +104,7 @@ public Status execute(LightLambdaExchange exchange) {
if(metricsMiddleware == null) lookupMetricsMiddleware();
if(metricsMiddleware != null) {
if (LOG.isTraceEnabled()) LOG.trace("Inject metrics for {}", CONFIG.getMetricsName());
- metricsMiddleware.injectMetrics(exchange, startTime, CONFIG.getMetricsName(), null);
+ metricsMiddleware.injectMetrics(exchange, startTime, CONFIG.getMetricsName());
}
}
if(LOG.isTraceEnabled()) LOG.trace("Response: {}", JsonMapper.toJson(res));
@@ -128,7 +128,7 @@ public Status execute(LightLambdaExchange exchange) {
if(metricsMiddleware == null) lookupMetricsMiddleware();
if(metricsMiddleware != null) {
if (LOG.isTraceEnabled()) LOG.trace("Inject metrics for {}", CONFIG.getMetricsName());
- metricsMiddleware.injectMetrics(exchange, startTime, CONFIG.getMetricsName(), null);
+ metricsMiddleware.injectMetrics(exchange, startTime, CONFIG.getMetricsName());
}
}
if(LOG.isTraceEnabled()) LOG.trace("Response: {}", JsonMapper.toJson(res));
diff --git a/src/main/resources/config/values.yml b/src/main/resources/config/values.yml
index 30d4d67..913e664 100644
--- a/src/main/resources/config/values.yml
+++ b/src/main/resources/config/values.yml
@@ -62,7 +62,7 @@ header.enabled: true
# handler.yml
handler.handlers:
# Light-framework cross-cutting concerns implemented in the microservice
- - com.networknt.aws.lambda.handler.middleware.metrics.APMMetricsMiddleware@metrics
+ - com.networknt.aws.lambda.handler.middleware.metrics.CloudWatchMetricsMiddleware@metrics
- com.networknt.aws.lambda.handler.middleware.correlation.CorrelationMiddleware@correlation
- com.networknt.aws.lambda.handler.middleware.traceability.TraceabilityMiddleware@traceability
- com.networknt.aws.lambda.handler.middleware.header.RequestHeaderMiddleware@requestHeader
@@ -87,6 +87,7 @@ handler.handlers:
- com.networknt.aws.lambda.handler.info.ServerInfoHandler@info
- com.networknt.aws.lambda.handler.logger.LoggerGetHandler@getLogger
- com.networknt.aws.lambda.handler.logger.LoggerSetHandler@setLogger
+ - com.networknt.aws.lambda.handler.cache.CacheExplorerHandler@cache
# client.yml
client.tokenKeyServerUrl: https://networknt.oktapreview.com
diff --git a/src/test/resources/config/values.yml b/src/test/resources/config/values.yml
index 4821fe4..9b1bebd 100644
--- a/src/test/resources/config/values.yml
+++ b/src/test/resources/config/values.yml
@@ -75,7 +75,7 @@ header.pathPrefixHeader:
# handler.yml
handler.handlers:
# Light-framework cross-cutting concerns implemented in the microservice
- - com.networknt.aws.lambda.handler.middleware.metrics.APMMetricsMiddleware@metrics
+ - com.networknt.aws.lambda.handler.middleware.metrics.CloudWatchMetricsMiddleware@metrics
- com.networknt.aws.lambda.handler.middleware.correlation.CorrelationMiddleware@correlation
- com.networknt.aws.lambda.handler.middleware.traceability.TraceabilityMiddleware@traceability
- com.networknt.aws.lambda.handler.middleware.header.RequestHeaderMiddleware@requestHeader