Skip to content

Commit 684ae20

Browse files
committed
Added support for log categories for application logs (via Marker)
Jersey HTTP header propagation based on @context HttpHeaders
1 parent 5e2e9ad commit 684ae20

File tree

22 files changed

+316
-47
lines changed

22 files changed

+316
-47
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ Stacktrace information in case the message is reporting an exception.
303303
NOTE: This MUST NOT contain NEWLINE or TAB characters!
304304

305305

306+
==== categories
307+
308+
type: string
309+
310+
required: False
311+
312+
A list of names to further categorize this log message.
313+
314+
306315
=== custom_fields Fields
307316

308317
A JSON object representing the custom arguments passed to the logging

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
@@ -18,6 +18,11 @@
1818
}
1919
],
2020
"properties": {
21+
"categories": {
22+
"doc_values": true,
23+
"index": "not_analyzed",
24+
"type": "string"
25+
},
2126
"component_id": {
2227
"doc_values": true,
2328
"index": "not_analyzed",

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ app-logs:
226226
227227
NOTE: This MUST NOT contain NEWLINE or TAB characters!
228228
229+
- name: "categories"
230+
type: string
231+
required: false
232+
description: |
233+
A list of names to further categorize this log message.
234+
229235
- name: "custom_fields"
230236
type: group
231237
required: false

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
@@ -28,6 +28,7 @@ public interface Fields {
2828
public String LEVEL = "level";
2929
public String MSG = "msg";
3030
public String STACKTRACE = "stacktrace";
31+
public String CATEGORIES = "categories";
3132
public String CUSTOM_FIELDS = "custom_fields";
3233
public String REQUEST_ID = "request_id";
3334
public String REQUEST = "request";

cf-java-logging-support-jersey/src/main/java/com/sap/hcp/cf/logging/jersey/filter/ClientRequestUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
public class ClientRequestUtils {
1111

12-
public static Invocation.Builder propagate(Invocation.Builder builder, ContainerRequest req) {
12+
public static Invocation.Builder propagate(Invocation.Builder builder, javax.ws.rs.core.HttpHeaders reqHeaders) {
1313
if (LogContext.getCorrelationId() == null) {
14-
LogContext.initializeContext(req != null ? req.getHeaderString(HttpHeaders.CORRELATION_ID) : null);
14+
LogContext.initializeContext(reqHeaders != null ? reqHeaders.getHeaderString(HttpHeaders.CORRELATION_ID) : null);
1515
}
1616
builder.header(HttpHeaders.CORRELATION_ID, LogContext.getCorrelationId());
1717
return builder;

cf-java-logging-support-jersey/src/test/java/com/sap/hcp/cf/logging/jersey/filter/TestChainedResource.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import javax.ws.rs.client.ClientBuilder;
77
import javax.ws.rs.client.WebTarget;
88
import javax.ws.rs.core.Context;
9+
import javax.ws.rs.core.HttpHeaders;
910
import javax.ws.rs.core.Response;
1011
import javax.ws.rs.core.UriInfo;
1112

@@ -21,7 +22,7 @@
2122
public class TestChainedResource {
2223

2324
@GET
24-
public Response getHello(@Context UriInfo ui, @Context ContainerRequest req) {
25+
public Response getHello(@Context UriInfo ui, @Context HttpHeaders reqHeaders) {
2526

2627
ClientConfig cfg = new ClientConfig();
2728
cfg.register(RequestMetricsClientRequestFilter.class);
@@ -32,7 +33,7 @@ public Response getHello(@Context UriInfo ui, @Context ContainerRequest req) {
3233
/*
3334
* -- As this may get executed in a different thread, propagate
3435
*/
35-
return ClientRequestUtils.propagate(wt.request(), req).get();
36+
return ClientRequestUtils.propagate(wt.request(), reqHeaders).get();
3637
}
3738

3839
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.sap.hcp.cf.log4j2.converter;
2+
3+
import com.fasterxml.jackson.jr.ob.JSON;
4+
import com.fasterxml.jackson.jr.ob.JSONComposer;
5+
import com.fasterxml.jackson.jr.ob.comp.ArrayComposer;
6+
import org.apache.logging.log4j.Marker;
7+
import org.apache.logging.log4j.core.LogEvent;
8+
import org.apache.logging.log4j.core.config.plugins.Plugin;
9+
import org.apache.logging.log4j.core.pattern.ConverterKeys;
10+
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
11+
import org.slf4j.LoggerFactory;
12+
13+
import java.io.IOException;
14+
import java.util.Iterator;
15+
16+
@Plugin(name="CategoriesConverter", category="Converter")
17+
@ConverterKeys({"categories"})
18+
public class CategoriesConverter extends LogEventPatternConverter {
19+
20+
public static final String WORD = "categories";
21+
22+
public CategoriesConverter(String[] options) {
23+
super(WORD, WORD);
24+
}
25+
26+
public static CategoriesConverter newInstance(final String[] options) {
27+
return new CategoriesConverter(options);
28+
}
29+
30+
@Override
31+
public void format(LogEvent event, StringBuilder toAppendTo) {
32+
getMarkers(event.getMarker(), toAppendTo);
33+
}
34+
35+
private void getMarkers(Marker marker, StringBuilder toAppendTo) {
36+
try {
37+
ArrayComposer<JSONComposer<String>> ac = JSON.std.composeString().startArray();
38+
getMarkersRecursively(marker, ac);
39+
toAppendTo.append(ac.end().finish());
40+
} catch (IOException ex) {
41+
LoggerFactory.getLogger(CategoriesConverter.class).error("conversion failed", ex);
42+
}
43+
}
44+
45+
private void getMarkersRecursively(Marker marker, ArrayComposer<JSONComposer<String>> ac) throws IOException {
46+
if (marker != null) {
47+
ac.add(marker.getName());
48+
Marker[] parents = marker.getParents();
49+
if (parents != null) {
50+
for (Marker parent : parents) {
51+
getMarkersRecursively(parent, ac);
52+
}
53+
}
54+
}
55+
}
56+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.sap.hcp.cf.log4j2.converter;
2+
3+
import org.apache.logging.log4j.core.LogEvent;
4+
import org.apache.logging.log4j.core.config.plugins.Plugin;
5+
import org.apache.logging.log4j.core.pattern.ConverterKeys;
6+
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
7+
8+
@Plugin(name="TimestampConverter", category="Converter")
9+
@ConverterKeys({"tstamp"})
10+
public class TimestampConverter extends LogEventPatternConverter {
11+
12+
public static final String WORD = "tstamp";
13+
14+
public TimestampConverter(String[] options) {
15+
super(WORD, WORD);
16+
}
17+
18+
public static TimestampConverter newInstance(final String[] options) {
19+
return new TimestampConverter(options);
20+
}
21+
22+
@Override
23+
public void format(LogEvent event, StringBuilder toAppendTo) {
24+
toAppendTo.append(System.nanoTime());
25+
}
26+
27+
}

cf-java-logging-support-log4j2/src/main/java/com/sap/hcp/cf/log4j2/layout/LayoutPatterns.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public enum PATTERN_KEY {
2424
*/
2525
private static final String COMMON_PREFIX_PATTERN =
2626
"{ " +
27-
JSON_FIELD(Fields.WRITTEN_AT, "%d{yyyy-MM-dd'T'HH:mm:ss.SSSX}{UTC}", true, false) +
27+
JSON_FIELD(Fields.WRITTEN_AT, "%d{yyyy-MM-dd'T'HH:mm:ss.SSSX}{UTC}", true, true) +
28+
JSON_FIELD(Fields.WRITTEN_TS, "%tstamp", false, false) +
2829
"%replace{%ctxp}{(.+)}{,$1},";
2930

3031
/*
@@ -43,6 +44,7 @@ public enum PATTERN_KEY {
4344
JSON_FIELD(Fields.LOGGER, "%logger", true, true) +
4445
JSON_FIELD(Fields.THREAD, "%thread", true, true) +
4546
JSON_FIELD(Fields.LEVEL, "%p", true, true) +
47+
JSON_FIELD(Fields.CATEGORIES, "%categories", false, true) +
4648
JSON_FIELD(Fields.MSG, "%jsonmsg{escape}%replace{%args{custom_fields}}{(.+)}{,$1}", false, false);
4749

4850
/*

cf-java-logging-support-log4j2/src/test/java/com/sap/hcp/cf/logging/common/AbstractTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.ByteArrayOutputStream;
44
import java.io.PrintStream;
5+
import java.util.List;
56
import java.util.Map;
67

78
import org.junit.After;
@@ -43,6 +44,15 @@ protected String getField(String fieldName) {
4344
}
4445
}
4546

47+
protected List<String> getList(String fieldName) {
48+
try {
49+
return (List<String>)JSON.std.mapFrom(getLastLine()).get(fieldName);
50+
} catch (Exception ex) {
51+
ex.printStackTrace();
52+
return null;
53+
}
54+
}
55+
4656
private String getLastLine() {
4757
String[] lines = this.outContent.toString().split("\n");
4858
return lines[lines.length-1];

0 commit comments

Comments
 (0)