Skip to content

Commit 7375970

Browse files
authored
Merge pull request #9121 from github/igfoo/mjson
Kotlin: Write the log file as Line-delimited JSON
2 parents aba4a9a + e319ab1 commit 7375970

File tree

3 files changed

+64
-35
lines changed

3 files changed

+64
-35
lines changed

java/kotlin-extractor/src/main/kotlin/utils/Logger.kt

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,36 @@ enum class Severity(val sev: Int) {
3333
ErrorGlobal(8)
3434
}
3535

36+
class LogMessage(private val kind: String, private val message: String) {
37+
val timestamp: String
38+
init {
39+
timestamp = "${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}"
40+
}
41+
42+
fun toText(): String {
43+
return "[$timestamp K] [$kind] $message"
44+
}
45+
46+
private fun escape(str: String): String {
47+
return str.replace("\\", "\\\\")
48+
.replace("\"", "\\\"")
49+
.replace("/", "\\/")
50+
.replace("\b", "\\b")
51+
.replace("\u000C", "\\f")
52+
.replace("\n", "\\n")
53+
.replace("\r", "\\r")
54+
.replace("\t", "\\t")
55+
}
56+
57+
fun toJsonLine(): String {
58+
val kvs = listOf(Pair("origin", "CodeQL Kotlin extractor"),
59+
Pair("timestamp", timestamp),
60+
Pair("kind", kind),
61+
Pair("message", message))
62+
return "{ " + kvs.map { p -> "\"${p.first}\": \"${escape(p.second)}\""}.joinToString(", ") + " }\n"
63+
}
64+
}
65+
3666
data class ExtractorContext(val kind: String, val element: IrElement, val name: String, val loc: String)
3767

3868
open class LoggerBase(val logCounter: LogCounter) {
@@ -54,10 +84,6 @@ open class LoggerBase(val logCounter: LogCounter) {
5484
}
5585
}
5686

57-
private fun timestamp(): String {
58-
return "[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())} K]"
59-
}
60-
6187
private fun getDiagnosticLocation(): String? {
6288
val st = Exception().stackTrace
6389
for(x in st) {
@@ -84,7 +110,6 @@ open class LoggerBase(val logCounter: LogCounter) {
84110
fun diagnostic(tw: TrapWriter, severity: Severity, msg: String, extraInfo: String?, locationString: String? = null, mkLocationId: () -> Label<DbLocation> = { tw.unknownLocation }) {
85111
val diagnosticLoc = getDiagnosticLocation()
86112
val diagnosticLocStr = if(diagnosticLoc == null) "<unknown location>" else diagnosticLoc
87-
val extraInfoStr = if (extraInfo == null) "" else (extraInfo + "\n")
88113
val suffix =
89114
if(diagnosticLoc == null) {
90115
" Missing caller information.\n"
@@ -100,8 +125,10 @@ open class LoggerBase(val logCounter: LogCounter) {
100125
}
101126
val fullMsgBuilder = StringBuilder()
102127
fullMsgBuilder.append(msg)
103-
fullMsgBuilder.append('\n')
104-
fullMsgBuilder.append(extraInfoStr)
128+
if (extraInfo != null) {
129+
fullMsgBuilder.append('\n')
130+
fullMsgBuilder.append(extraInfo)
131+
}
105132

106133
val iter = extractorContextStack.listIterator(extractorContextStack.size)
107134
while (iter.hasPrevious()) {
@@ -111,38 +138,38 @@ open class LoggerBase(val logCounter: LogCounter) {
111138
fullMsgBuilder.append(suffix)
112139

113140
val fullMsg = fullMsgBuilder.toString()
114-
val ts = timestamp()
141+
val locStr = if (locationString == null) "" else "At " + locationString + ": "
142+
val kind = if (severity <= Severity.WarnHigh) "WARN" else "ERROR"
143+
val logMessage = LogMessage(kind, "Diagnostic($diagnosticLocStr): $locStr$fullMsg")
115144
// We don't actually make the location until after the `return` above
116145
val locationId = mkLocationId()
117146
val diagLabel = tw.getFreshIdLabel<DbDiagnostic>()
118-
tw.writeDiagnostics(diagLabel, "CodeQL Kotlin extractor", severity.sev, "", msg, "$ts $fullMsg", locationId)
147+
tw.writeDiagnostics(diagLabel, "CodeQL Kotlin extractor", severity.sev, "", msg, "${logMessage.timestamp} $fullMsg", locationId)
119148
tw.writeDiagnostic_for(diagLabel, StringLabel("compilation"), file_number, file_number_diagnostic_number++)
120-
val locStr = if (locationString == null) "" else "At " + locationString + ": "
121-
val kind = if (severity <= Severity.WarnHigh) "WARN" else "ERROR"
122-
logStream.write("$ts [$kind] Diagnostic($diagnosticLocStr): $locStr$fullMsg")
149+
logStream.write(logMessage.toJsonLine())
123150
}
124151

125152
fun trace(tw: TrapWriter, msg: String) {
126153
if (verbosity >= 4) {
127-
val fullMsg = "${timestamp()} [TRACE] $msg"
128-
tw.writeComment(fullMsg)
129-
logStream.write(fullMsg + "\n")
154+
val logMessage = LogMessage("TRACE", msg)
155+
tw.writeComment(logMessage.toText())
156+
logStream.write(logMessage.toJsonLine())
130157
}
131158
}
132159

133160
fun debug(tw: TrapWriter, msg: String) {
134161
if (verbosity >= 4) {
135-
val fullMsg = "${timestamp()} [DEBUG] $msg"
136-
tw.writeComment(fullMsg)
137-
logStream.write(fullMsg + "\n")
162+
val logMessage = LogMessage("DEBUG", msg)
163+
tw.writeComment(logMessage.toText())
164+
logStream.write(logMessage.toJsonLine())
138165
}
139166
}
140167

141168
fun info(tw: TrapWriter, msg: String) {
142169
if (verbosity >= 3) {
143-
val fullMsg = "${timestamp()} [INFO] $msg"
144-
tw.writeComment(fullMsg)
145-
logStream.write(fullMsg + "\n")
170+
val logMessage = LogMessage("INFO", msg)
171+
tw.writeComment(logMessage.toText())
172+
logStream.write(logMessage.toJsonLine())
146173
}
147174
}
148175

@@ -160,9 +187,12 @@ open class LoggerBase(val logCounter: LogCounter) {
160187
fun printLimitedDiagnosticCounts(tw: TrapWriter) {
161188
for((caller, count) in logCounter.diagnosticCounts) {
162189
if(count >= logCounter.diagnosticLimit) {
163-
val msg = "Total of $count diagnostics from $caller.\n"
164-
tw.writeComment(msg)
165-
logStream.write(msg)
190+
// We don't know if this location relates to an error
191+
// or a warning, so we just declare hitting the limit
192+
// to be an error regardless.
193+
val logMessage = LogMessage("ERROR", "Total of $count diagnostics from $caller.")
194+
tw.writeComment(logMessage.toText())
195+
logStream.write(logMessage.toJsonLine())
166196
}
167197
}
168198
}

0 commit comments

Comments
 (0)