Skip to content

Commit d68415e

Browse files
authored
fix: structured logging (#250)
1 parent e76a262 commit d68415e

File tree

4 files changed

+121
-28
lines changed

4 files changed

+121
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
99

10+
## [8.0.3]
11+
12+
- Adds `USE_STRUCTURED_LOGGING` environment variable to control the logging format.
13+
1014
## [8.0.2]
1115

1216
- Fixes `NullPointerException` in user search API

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ plugins {
22
id 'java-library'
33
}
44

5-
version = "8.0.2"
5+
version = "8.0.3"
66

77
repositories {
88
mavenCentral()

src/main/java/io/supertokens/storage/postgresql/output/CustomLayout.java

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
import ch.qos.logback.classic.spi.ILoggingEvent;
2121
import ch.qos.logback.core.CoreConstants;
2222
import ch.qos.logback.core.LayoutBase;
23+
import com.google.gson.Gson;
24+
import com.google.gson.JsonArray;
25+
import com.google.gson.JsonElement;
26+
import com.google.gson.JsonObject;
2327
import io.supertokens.storage.postgresql.utils.Utils;
2428

2529
import java.text.DateFormat;
@@ -29,39 +33,82 @@
2933
class CustomLayout extends LayoutBase<ILoggingEvent> {
3034

3135
private final String processID;
36+
private boolean useStructuredLogging = false;
3237

3338
CustomLayout(String processID) {
3439
super();
3540
this.processID = processID;
41+
this.useStructuredLogging = Boolean.parseBoolean(System.getenv("USE_STRUCTURED_LOGGING"));
3642
}
3743

3844
@Override
3945
public String doLayout(ILoggingEvent event) {
40-
StringBuilder sbuf = new StringBuilder();
41-
46+
JsonObject msgObj = new Gson().fromJson(event.getMessage(), JsonObject.class);
4247
DateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss:SSS Z");
43-
sbuf.append(dateFormat.format(new Date(event.getTimeStamp())));
44-
sbuf.append(" | ");
4548

46-
sbuf.append(event.getLevel());
47-
sbuf.append(" | ");
49+
if (useStructuredLogging) {
50+
msgObj.addProperty("timestamp", dateFormat.format(new Date(event.getTimeStamp())));
51+
msgObj.addProperty("level", event.getLevel().toString());
52+
msgObj.addProperty("pid", this.processID);
53+
msgObj.addProperty("threadName", event.getThreadName());
54+
msgObj.addProperty("callerData", event.getCallerData()[1].toString());
55+
56+
return msgObj.toString() + CoreConstants.LINE_SEPARATOR;
57+
} else {
58+
StringBuilder sbuf = new StringBuilder();
59+
60+
if (msgObj.has("exception")) {
61+
JsonArray stackTraceObj = msgObj.get("exception").getAsJsonArray();
62+
sbuf.append(dateFormat.format(new Date(event.getTimeStamp())));
63+
sbuf.append(" | ");
64+
65+
sbuf.append(event.getLevel());
66+
sbuf.append(" | ");
67+
68+
sbuf.append("pid: ");
69+
sbuf.append(this.processID);
70+
sbuf.append(" | ");
71+
72+
sbuf.append("[");
73+
sbuf.append(event.getThreadName());
74+
sbuf.append("] thread");
75+
sbuf.append(" | ");
76+
77+
sbuf.append(event.getCallerData()[1]);
78+
sbuf.append(" | ");
79+
80+
for (JsonElement stackTraceElement : stackTraceObj) {
81+
sbuf.append(stackTraceElement.getAsString());
82+
sbuf.append(CoreConstants.LINE_SEPARATOR);
83+
}
84+
85+
sbuf.append(CoreConstants.LINE_SEPARATOR);
86+
sbuf.append(CoreConstants.LINE_SEPARATOR);
87+
}
88+
89+
sbuf.append(dateFormat.format(new Date(event.getTimeStamp())));
90+
sbuf.append(" | ");
91+
92+
sbuf.append(event.getLevel());
93+
sbuf.append(" | ");
4894

49-
sbuf.append("pid: ");
50-
sbuf.append(this.processID);
51-
sbuf.append(" | ");
95+
sbuf.append("pid: ");
96+
sbuf.append(this.processID);
97+
sbuf.append(" | ");
5298

53-
sbuf.append("[");
54-
sbuf.append(event.getThreadName());
55-
sbuf.append("] thread");
56-
sbuf.append(" | ");
99+
sbuf.append("[");
100+
sbuf.append(event.getThreadName());
101+
sbuf.append("] thread");
102+
sbuf.append(" | ");
57103

58-
sbuf.append(event.getCallerData()[1]);
59-
sbuf.append(" | ");
104+
sbuf.append(event.getCallerData()[1]);
105+
sbuf.append(" | ");
60106

61-
sbuf.append(Utils.maskDBPassword(event.getFormattedMessage()));
62-
sbuf.append(CoreConstants.LINE_SEPARATOR);
63-
sbuf.append(CoreConstants.LINE_SEPARATOR);
107+
sbuf.append(Utils.maskDBPassword(event.getFormattedMessage()));
108+
sbuf.append(CoreConstants.LINE_SEPARATOR);
109+
sbuf.append(CoreConstants.LINE_SEPARATOR);
64110

65-
return sbuf.toString();
111+
return sbuf.toString();
112+
}
66113
}
67114
}

src/main/java/io/supertokens/storage/postgresql/output/Logging.java

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,19 @@
2222
import ch.qos.logback.classic.spi.ILoggingEvent;
2323
import ch.qos.logback.core.ConsoleAppender;
2424
import ch.qos.logback.core.FileAppender;
25+
import com.google.gson.JsonArray;
26+
import com.google.gson.JsonObject;
27+
import com.google.gson.JsonPrimitive;
2528
import io.supertokens.pluginInterface.LOG_LEVEL;
2629
import io.supertokens.storage.postgresql.ResourceDistributor;
2730
import io.supertokens.storage.postgresql.Start;
2831
import io.supertokens.storage.postgresql.config.Config;
2932
import io.supertokens.storage.postgresql.utils.Utils;
3033
import org.slf4j.LoggerFactory;
3134

35+
import java.io.ByteArrayOutputStream;
36+
import java.io.PrintStream;
37+
3238
public class Logging extends ResourceDistributor.SingletonResource {
3339

3440
private static final String RESOURCE_ID = "io.supertokens.storage.postgresql.output.Logging";
@@ -65,24 +71,59 @@ public static void debug(Start start, String msg) {
6571
try {
6672
msg = msg.trim();
6773
if (getInstance(start) != null) {
68-
getInstance(start).infoLogger.debug(msg);
74+
getInstance(start).infoLogger.debug(getFormattedMessage(msg));
6975
}
7076
} catch (NullPointerException ignored) {
7177
}
7278
}
7379

80+
public static String throwableStacktraceToString(Throwable e) {
81+
if (e == null) {
82+
return "";
83+
}
84+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
85+
try (PrintStream ps = new PrintStream(baos)) {
86+
e.printStackTrace(ps);
87+
}
88+
return baos.toString();
89+
}
90+
91+
private static String getFormattedMessage(String msg, Exception e) {
92+
JsonObject msgObj = new JsonObject();
93+
msgObj.addProperty("message", msg);
94+
95+
if (e != null) {
96+
String stackTrace = throwableStacktraceToString(e);
97+
String[] stackTraceArr = stackTrace.split("\n");
98+
JsonArray stackTraceArrObj = new JsonArray();
99+
for (String stackTraceElement : stackTraceArr) {
100+
stackTraceArrObj.add(new JsonPrimitive(stackTraceElement));
101+
}
102+
103+
msgObj.add("exception", stackTraceArrObj);
104+
}
105+
106+
return msgObj.toString();
107+
}
108+
109+
private static String getFormattedMessage(String msg) {
110+
return getFormattedMessage(msg, null);
111+
}
112+
74113
public static void info(Start start, String msg, boolean toConsoleAsWell) {
75114
if (!Config.getLogLevels(start).contains(LOG_LEVEL.INFO)) {
76115
return;
77116
}
78117
try {
79118
msg = msg.trim();
80-
if (getInstance(start) != null) {
81-
getInstance(start).infoLogger.info(msg);
82-
}
83119
if (toConsoleAsWell) {
84120
systemOut(msg);
85121
}
122+
msg = getFormattedMessage(msg);
123+
124+
if (getInstance(start) != null) {
125+
getInstance(start).infoLogger.info(msg);
126+
}
86127
} catch (NullPointerException ignored) {
87128
}
88129
}
@@ -93,6 +134,7 @@ public static void warn(Start start, String msg) {
93134
}
94135
try {
95136
msg = msg.trim();
137+
msg = getFormattedMessage(msg);
96138
if (getInstance(start) != null) {
97139
getInstance(start).errorLogger.warn(msg);
98140
}
@@ -113,7 +155,7 @@ public static void error(Start start, String err, boolean toConsoleAsWell) {
113155
try {
114156
err = err.trim();
115157
if (getInstance(start) != null) {
116-
getInstance(start).errorLogger.error(err);
158+
getInstance(start).errorLogger.error(getFormattedMessage(err));
117159
}
118160
if (toConsoleAsWell || getInstance(start) == null) {
119161
systemErr(err);
@@ -122,7 +164,8 @@ public static void error(Start start, String err, boolean toConsoleAsWell) {
122164
}
123165
}
124166

125-
public static void error(Start start, String message, boolean toConsoleAsWell, Exception e) {
167+
public static void error(Start start, String message, boolean toConsoleAsWell,
168+
Exception e) {
126169
try {
127170
if (!Config.getLogLevels(start).contains(LOG_LEVEL.ERROR)) {
128171
return;
@@ -142,7 +185,7 @@ public static void error(Start start, String message, boolean toConsoleAsWell, E
142185
if (message != null) {
143186
message = message.trim();
144187
if (getInstance(start) != null) {
145-
getInstance(start).errorLogger.error(message);
188+
getInstance(start).errorLogger.error(getFormattedMessage(message, e));
146189
}
147190
if (toConsoleAsWell || getInstance(start) == null) {
148191
systemErr(message);
@@ -220,5 +263,4 @@ private Logger createLoggerForConsole(Start start, String name, LOG_LEVEL logLev
220263

221264
return logger;
222265
}
223-
224266
}

0 commit comments

Comments
 (0)