2
2
3
3
import com .networknt .aws .lambda .handler .MiddlewareHandler ;
4
4
import com .networknt .aws .lambda .LightLambdaExchange ;
5
+ import com .networknt .aws .lambda .handler .middleware .audit .AuditMiddleware ;
5
6
import com .networknt .config .JsonMapper ;
6
7
import com .networknt .metrics .JVMMetricsDbReporter ;
7
8
import com .networknt .metrics .MetricsConfig ;
8
9
import com .networknt .metrics .TimeSeriesDbSender ;
9
10
import com .networknt .status .Status ;
10
11
import com .networknt .utility .Constants ;
12
+ import io .dropwizard .metrics .Metric ;
11
13
import io .dropwizard .metrics .MetricFilter ;
12
14
import io .dropwizard .metrics .MetricName ;
13
15
import io .dropwizard .metrics .MetricRegistry ;
14
16
import org .slf4j .Logger ;
15
17
import org .slf4j .LoggerFactory ;
18
+ import software .amazon .cloudwatchlogs .emf .logger .MetricsLogger ;
19
+ import software .amazon .cloudwatchlogs .emf .model .MetricsContext ;
20
+ import software .amazon .cloudwatchlogs .emf .model .Unit ;
16
21
17
22
import java .util .HashMap ;
18
23
import java .util .Map ;
24
29
25
30
public abstract class AbstractMetricsMiddleware implements MiddlewareHandler {
26
31
static final Logger logger = LoggerFactory .getLogger (AbstractMetricsMiddleware .class );
32
+ public static final LightLambdaExchange .Attachable <AbstractMetricsMiddleware > METRICS_LOGGER_ATTACHMENT_KEY = LightLambdaExchange .Attachable .createAttachable (AbstractMetricsMiddleware .class );
27
33
// The metrics.yml configuration that supports reload.
28
34
public static MetricsConfig config ;
29
- static Pattern pattern ;
30
- // The structure that collect all the metrics entries. Even others will be using this structure to inject.
31
- public static final MetricRegistry registry = new MetricRegistry ();
32
- public Map <String , String > commonTags = new HashMap <>();
33
35
34
36
public AbstractMetricsMiddleware () {
35
37
}
36
38
37
-
38
39
@ Override
39
40
public boolean isEnabled () {
40
41
return config .isEnabled ();
41
42
}
42
43
43
- public void createJVMMetricsReporter (final TimeSeriesDbSender sender ) {
44
- JVMMetricsDbReporter jvmReporter = new JVMMetricsDbReporter (new MetricRegistry (), sender , "jvm-reporter" ,
45
- MetricFilter .ALL , TimeUnit .SECONDS , TimeUnit .MILLISECONDS , commonTags );
46
- jvmReporter .start (config .getReportInMinutes (), TimeUnit .MINUTES );
47
- }
48
-
49
- public void incCounterForStatusCode (int statusCode , Map <String , String > commonTags , Map <String , String > tags ) {
50
- MetricName metricName = new MetricName ("request" ).tagged (commonTags ).tagged (tags );
51
- registry .getOrAdd (metricName , MetricRegistry .MetricBuilder .COUNTERS ).inc ();
44
+ public void incCounterForStatusCode (MetricsLogger metricsLogger , int statusCode ) {
45
+ metricsLogger .putMetric ("request" , 1 , Unit .COUNT );
52
46
if (statusCode >= 200 && statusCode < 400 ) {
53
- metricName = new MetricName ("success" ).tagged (commonTags ).tagged (tags );
54
- registry .getOrAdd (metricName , MetricRegistry .MetricBuilder .COUNTERS ).inc ();
47
+ metricsLogger .putMetric ("success" , 1 , Unit .COUNT );
55
48
} else if (statusCode == 401 || statusCode == 403 ) {
56
- metricName = new MetricName ("auth_error" ).tagged (commonTags ).tagged (tags );
57
- registry .getOrAdd (metricName , MetricRegistry .MetricBuilder .COUNTERS ).inc ();
49
+ metricsLogger .putMetric ("auth_error" , 1 , Unit .COUNT );
58
50
} else if (statusCode >= 400 && statusCode < 500 ) {
59
- metricName = new MetricName ("request_error" ).tagged (commonTags ).tagged (tags );
60
- registry .getOrAdd (metricName , MetricRegistry .MetricBuilder .COUNTERS ).inc ();
51
+ metricsLogger .putMetric ("request_error" , 1 , Unit .COUNT );
61
52
} else if (statusCode >= 500 ) {
62
- metricName = new MetricName ("server_error" ).tagged (commonTags ).tagged (tags );
63
- registry .getOrAdd (metricName , MetricRegistry .MetricBuilder .COUNTERS ).inc ();
53
+ metricsLogger .putMetric ("server_error" , 1 , Unit .COUNT );
64
54
}
65
55
}
66
56
@@ -70,69 +60,17 @@ public void incCounterForStatusCode(int statusCode, Map<String, String> commonTa
70
60
* @param exchange the LightLambdaExchange that is used to get the auditInfo to collect the metrics tag.
71
61
* @param startTime the start time passed in to calculate the response time.
72
62
* @param metricsName the name of the metrics that is collected.
73
- * @param endpoint the endpoint that is used to collect the metrics. It is optional and only provided by the external handlers.
74
63
*/
75
- public void injectMetrics (LightLambdaExchange exchange , long startTime , String metricsName , String endpoint ) {
76
- Map <String , Object > auditInfo = (Map <String , Object >)exchange .getAttachment (AUDIT_ATTACHMENT_KEY );
77
- if (logger .isTraceEnabled ()) logger .trace ("auditInfo = " + auditInfo );
78
- Map <String , String > tags = new HashMap <>();
79
- if (auditInfo != null ) {
80
- // for external handlers, the endpoint must be unknown in the auditInfo. If that is the case, use the endpoint passed in.
81
- if (endpoint != null ) {
82
- tags .put (Constants .ENDPOINT_STRING , endpoint );
83
- } else {
84
- tags .put (Constants .ENDPOINT_STRING , (String ) auditInfo .get (Constants .ENDPOINT_STRING ));
85
- }
86
- String clientId = auditInfo .get (Constants .CLIENT_ID_STRING ) != null ? (String ) auditInfo .get (Constants .CLIENT_ID_STRING ) : "unknown" ;
87
- if (logger .isTraceEnabled ()) logger .trace ("clientId = {}" , clientId );
88
- tags .put ("clientId" , clientId );
89
- // scope client id will only be available if two token is used. For example, authorization code flow.
90
- if (config .isSendScopeClientId ()) {
91
- tags .put ("scopeClientId" , auditInfo .get (Constants .SCOPE_CLIENT_ID_STRING ) != null ? (String ) auditInfo .get (Constants .SCOPE_CLIENT_ID_STRING ) : "unknown" );
92
- }
93
- // caller id is the calling serviceId that is passed from the caller. It is not always available but some organizations enforce it.
94
- if (config .isSendCallerId ()) {
95
- tags .put ("callerId" , auditInfo .get (Constants .CALLER_ID_STRING ) != null ? (String ) auditInfo .get (Constants .CALLER_ID_STRING ) : "unknown" );
96
- }
97
- if (config .isSendIssuer ()) {
98
- String issuer = (String ) auditInfo .get (Constants .ISSUER_CLAIMS );
99
- if (issuer != null ) {
100
- // we need to send issuer as a tag. Do we need to apply regex to extract only a part of the issuer?
101
- if (config .getIssuerRegex () != null ) {
102
- Matcher matcher = pattern .matcher (issuer );
103
- if (matcher .find ()) {
104
- String iss = matcher .group (1 );
105
- if (logger .isTraceEnabled ()) logger .trace ("Extracted issuer {} from Original issuer {] is sent." , iss , issuer );
106
- tags .put ("issuer" , iss != null ? iss : "unknown" );
107
- }
108
- } else {
109
- if (logger .isTraceEnabled ()) logger .trace ("Original issuer {} is sent." , issuer );
110
- tags .put ("issuer" , issuer );
111
- }
112
- }
113
- }
114
- } else {
115
- // for MRAS and Salesforce handlers that do not have auditInfo in the exchange as they may be called anonymously.
116
- tags .put (Constants .ENDPOINT_STRING , endpoint == null ? "unknown" : endpoint );
117
- tags .put ("clientId" , "unknown" );
118
- if (config .isSendScopeClientId ()) {
119
- tags .put ("scopeClientId" , "unknown" );
120
- }
121
- if (config .isSendCallerId ()) {
122
- tags .put ("callerId" , "unknown" );
123
- }
124
- if (config .isSendIssuer ()) {
125
- tags .put ("issuer" , "unknown" );
126
- }
64
+ public void injectMetrics (LightLambdaExchange exchange , long startTime , String metricsName ) {
65
+ MetricsLogger metricsLogger = (exchange .getAttachment (METRICS_LOGGER_ATTACHMENT_KEY ) != null ) ? (MetricsLogger ) exchange .getAttachment (METRICS_LOGGER_ATTACHMENT_KEY ) : null ;
66
+ if (metricsLogger == null ) {
67
+ if (logger .isTraceEnabled ()) logger .trace ("metricsContext is null, create one." );
68
+ metricsLogger = new MetricsLogger ();
69
+ exchange .addAttachment (METRICS_LOGGER_ATTACHMENT_KEY , metricsLogger );
127
70
}
128
- MetricName metricName = new MetricName (metricsName );
129
- metricName = metricName .tagged (commonTags );
130
- metricName = metricName .tagged (tags );
131
- long time = System .nanoTime () - startTime ;
132
- registry .getOrAdd (metricName , MetricRegistry .MetricBuilder .TIMERS ).update (time , TimeUnit .NANOSECONDS );
71
+ long time = System .currentTimeMillis () - startTime ;
72
+ metricsLogger .putMetric (metricsName , time , Unit .MILLISECONDS );
133
73
if (logger .isTraceEnabled ())
134
- logger .trace ("metricName = {} commonTags = {} tags = {}" , metricName , JsonMapper .toJson (commonTags ), JsonMapper .toJson (tags ));
135
- // the metrics handler will collect the status code metrics and increase the counter. Here we don't want to increase it again.
136
- // incCounterForStatusCode(httpServerExchange.getStatusCode(), commonTags, tags);
74
+ logger .trace ("metricName {} is injected with time {}" , metricsName , time );
137
75
}
138
76
}
0 commit comments