Skip to content

Commit 57e8638

Browse files
Merge pull request #139 from SAP/w3c_traceparent
Add support for W3C traceparent HTTP header
2 parents 6e40037 + b71cc83 commit 57e8638

File tree

13 files changed

+152
-11
lines changed

13 files changed

+152
-11
lines changed

cf-java-logging-support-core/beats/app-logs/docs/fields.asciidoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ required: False
9191
A unique identifier that can be used to correlate multiple messages to a request.
9292

9393

94+
==== w3c_traceparent
95+
96+
type: string
97+
98+
example: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
99+
100+
required: False
101+
102+
The content of the W3C traceparent header as defined in
103+
https://www.w3.org/TR/trace-context/#traceparent-header.
104+
The traceparent allows correlation of logs to the request.
105+
106+
94107
==== sap_passport
95108

96109
type: string

cf-java-logging-support-core/beats/app-logs/etc/app-logs.template.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@
198198
"index": "not_analyzed",
199199
"type": "string"
200200
},
201+
"w3c_traceparent": {
202+
"doc_values": true,
203+
"index": "not_analyzed",
204+
"type": "string"
205+
},
201206
"written_at": {
202207
"doc_values": true,
203208
"ignore_malformed": true,

cf-java-logging-support-core/beats/app-logs/etc/fields.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ ctx:
7676
description: |
7777
A unique identifier that can be used to correlate multiple messages to a request.
7878
79+
- name: "w3c_traceparent"
80+
type: string
81+
required: false
82+
example: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
83+
description: |
84+
The content of the W3C traceparent header as defined in
85+
https://www.w3.org/TR/trace-context/#traceparent-header.
86+
The traceparent allows correlation of logs to the request.
87+
7988
- name: "sap_passport"
8089
type: string
8190
required: false

cf-java-logging-support-core/beats/request-metrics/docs/fields.asciidoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ required: False
100100
A unique identifier that can be used to correlate multiple messages to a request.
101101

102102

103+
==== w3c_traceparent
104+
105+
type: string
106+
107+
example: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
108+
109+
required: False
110+
111+
The content of the W3C traceparent header as defined in
112+
https://www.w3.org/TR/trace-context/#traceparent-header.
113+
The traceparent allows correlation of logs to the request.
114+
115+
103116
==== sap_passport
104117

105118
type: string

cf-java-logging-support-core/beats/request-metrics/etc/fields.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ ctx:
8585
description: |
8686
A unique identifier that can be used to correlate multiple messages to a request.
8787
88+
- name: "w3c_traceparent"
89+
type: string
90+
required: false
91+
example: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
92+
description: |
93+
The content of the W3C traceparent header as defined in
94+
https://www.w3.org/TR/trace-context/#traceparent-header.
95+
The traceparent allows correlation of logs to the request.
96+
8897
- name: "sap_passport"
8998
type: string
9099
required: false

cf-java-logging-support-core/beats/request-metrics/etc/request-metrics.template.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@
263263
"index": "not_analyzed",
264264
"type": "string"
265265
},
266+
"w3c_traceparent": {
267+
"doc_values": true,
268+
"index": "not_analyzed",
269+
"type": "string"
270+
},
266271
"written_at": {
267272
"doc_values": true,
268273
"ignore_malformed": true,

cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/Fields.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public interface Fields {
1313
public String WRITTEN_TS = "written_ts";
1414
public String CORRELATION_ID = "correlation_id";
1515
public String REQUEST_ID = "request_id";
16+
public String W3C_TRACEPARENT = "w3c_traceparent";
1617
public String SAP_PASSPORT = "sap_passport";
1718
public String SAP_PASSPORT_ACTION = "sap_passport_Action";
1819
public String SAP_PASSPORT_ACTIONTYPE = "sap_passport_ActionType";

cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/request/HttpHeaders.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public enum HttpHeaders implements HttpHeader {
3636
X_VCAP_REQUEST_ID("x-vcap-request-id", Fields.REQUEST_ID, true), //
3737
CORRELATION_ID("X-CorrelationID", Fields.CORRELATION_ID, true,
3838
X_VCAP_REQUEST_ID), //
39+
W3C_TRACEPARENT("traceparent", Fields.W3C_TRACEPARENT, true),
3940
SAP_PASSPORT("sap-passport", Fields.SAP_PASSPORT, true), //
4041
TENANT_ID("tenantid", Fields.TENANT_ID, true); //
4142

cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/request/HttpHeadersTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void resetLogContext() {
2424

2525
@Test
2626
public void hasCorrectNumberOfTypes() throws Exception {
27-
assertThat(HttpHeaders.values().length, is(equalTo(19)));
27+
assertThat(HttpHeaders.values().length, is(equalTo(20)));
2828
}
2929

3030
@Test
@@ -34,6 +34,7 @@ public void hasCorrectNames() throws Exception {
3434
assertThat(HttpHeaders.CORRELATION_ID.getName(), is("X-CorrelationID"));
3535
assertThat(HttpHeaders.REFERER.getName(), is("referer"));
3636
assertThat(HttpHeaders.TENANT_ID.getName(), is("tenantid"));
37+
assertThat(HttpHeaders.W3C_TRACEPARENT.getName(), is("traceparent"));
3738
assertThat(HttpHeaders.X_CUSTOM_HOST.getName(), is("x-custom-host"));
3839
assertThat(HttpHeaders.X_FORWARDED_FOR.getName(), is("x-forwarded-for"));
3940
assertThat(HttpHeaders.X_FORWARDED_HOST.getName(), is("x-forwarded-host"));
@@ -56,6 +57,7 @@ public void hasCorrectFields() throws Exception {
5657
assertThat(HttpHeaders.CORRELATION_ID.getField(), is(Fields.CORRELATION_ID));
5758
assertThat(HttpHeaders.REFERER.getField(), is(nullValue()));
5859
assertThat(HttpHeaders.TENANT_ID.getField(), is(Fields.TENANT_ID));
60+
assertThat(HttpHeaders.W3C_TRACEPARENT.getField(), is(Fields.W3C_TRACEPARENT));
5961
assertThat(HttpHeaders.X_CUSTOM_HOST.getField(), is(Fields.X_CUSTOM_HOST));
6062
assertThat(HttpHeaders.X_FORWARDED_FOR.getField(), is(Fields.X_FORWARDED_FOR));
6163
assertThat(HttpHeaders.X_FORWARDED_HOST.getField(), is(Fields.X_FORWARDED_HOST));
@@ -93,6 +95,7 @@ public void hasCorrectAliases() throws Exception {
9395
assertThat(HttpHeaders.CORRELATION_ID.getAliases(), containsInAnyOrder(HttpHeaders.X_VCAP_REQUEST_ID));
9496
assertThat(HttpHeaders.REFERER.getAliases(), is(empty()));
9597
assertThat(HttpHeaders.TENANT_ID.getAliases(), is(empty()));
98+
assertThat(HttpHeaders.W3C_TRACEPARENT.getAliases(), is(empty()));
9699
assertThat(HttpHeaders.X_CUSTOM_HOST.getAliases(), is(empty()));
97100
assertThat(HttpHeaders.X_FORWARDED_FOR.getAliases(), is(empty()));
98101
assertThat(HttpHeaders.X_FORWARDED_HOST.getAliases(), is(empty()));
@@ -111,7 +114,8 @@ public void hasCorrectAliases() throws Exception {
111114
@Test
112115
public void propagatesCorrectHeaders() throws Exception {
113116
assertThat(HttpHeaders.propagated(), containsInAnyOrder(HttpHeaders.CORRELATION_ID, HttpHeaders.SAP_PASSPORT,
114-
HttpHeaders.TENANT_ID, HttpHeaders.X_VCAP_REQUEST_ID));
117+
HttpHeaders.TENANT_ID, HttpHeaders.W3C_TRACEPARENT,
118+
HttpHeaders.X_VCAP_REQUEST_ID));
115119
}
116120

117121
}

cf-java-logging-support-servlet/src/main/java/com/sap/hcp/cf/logging/servlet/filter/CorrelationIdFilter.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.sap.hcp.cf.logging.servlet.filter;
22

33
import static com.sap.hcp.cf.logging.common.customfields.CustomField.customField;
4+
import static com.sap.hcp.cf.logging.common.request.HttpHeaders.W3C_TRACEPARENT;
5+
import static java.util.Optional.ofNullable;
46

57
import java.util.UUID;
8+
import java.util.function.Predicate;
69

710
import javax.servlet.http.HttpServletRequest;
811
import javax.servlet.http.HttpServletResponse;
@@ -25,13 +28,19 @@ public class CorrelationIdFilter extends AbstractLoggingFilter {
2528

2629
private static final Logger LOG = LoggerFactory.getLogger(CorrelationIdFilter.class);
2730
private HttpHeader correlationHeader;
31+
private HttpHeader traceparentHeader;
2832

2933
public CorrelationIdFilter() {
3034
this(HttpHeaders.CORRELATION_ID);
3135
}
3236

3337
public CorrelationIdFilter(HttpHeader correlationHeader) {
38+
this(correlationHeader, W3C_TRACEPARENT);
39+
}
40+
41+
public CorrelationIdFilter(HttpHeader correlationHeader, HttpHeader traceparentHeader) {
3442
this.correlationHeader = correlationHeader;
43+
this.traceparentHeader = traceparentHeader;
3544
}
3645

3746
@Override
@@ -43,7 +52,10 @@ protected void beforeFilter(HttpServletRequest request, HttpServletResponse resp
4352

4453
private String determineCorrelationId(HttpServletRequest request) {
4554
String correlationId = HttpHeaderUtilities.getHeaderValue(request, correlationHeader);
46-
if (correlationId == null || correlationId.isEmpty() || correlationId.equals(Defaults.UNKNOWN)) {
55+
if (isBlankOrDefault(correlationId)) {
56+
correlationId = getCorrelationIdFromTraceparent(request);
57+
}
58+
if (isBlankOrDefault(correlationId)) {
4759
correlationId = String.valueOf(UUID.randomUUID());
4860
// add correlation-id as custom field, since it is added to MDC only
4961
// in the next step
@@ -53,6 +65,25 @@ private String determineCorrelationId(HttpServletRequest request) {
5365
return correlationId;
5466
}
5567

68+
private boolean isBlankOrDefault(String value) {
69+
return value == null || value.isEmpty() || value.equals(Defaults.UNKNOWN);
70+
}
71+
72+
private String getCorrelationIdFromTraceparent(HttpServletRequest request) {
73+
String traceparent = HttpHeaderUtilities.getHeaderValue(request, traceparentHeader);
74+
return ofNullable(traceparent).filter(not(this::isBlankOrDefault)).map(this::parseTraceparent).orElse(
75+
null);
76+
}
77+
78+
private <T> Predicate<T> not(Predicate<T> p) {
79+
return p.negate();
80+
}
81+
82+
private String parseTraceparent(String value) {
83+
String[] tokens = value.split("-");
84+
return tokens.length >= 2 ? tokens[1] : null;
85+
}
86+
5687
private void addCorrelationIdHeader(HttpServletResponse response, String correlationId) {
5788
if (!response.isCommitted() && response.getHeader(correlationHeader.getName()) == null) {
5889
response.setHeader(correlationHeader.getName(), correlationId);
@@ -63,5 +94,4 @@ private void addCorrelationIdHeader(HttpServletResponse response, String correla
6394
protected void cleanup(HttpServletRequest request, HttpServletResponse response) {
6495
LogContext.remove(correlationHeader.getField());
6596
}
66-
6797
}

0 commit comments

Comments
 (0)