@@ -33,6 +33,36 @@ enum class Severity(val sev: Int) {
33
33
ErrorGlobal (8 )
34
34
}
35
35
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
+
36
66
data class ExtractorContext (val kind : String , val element : IrElement , val name : String , val loc : String )
37
67
38
68
open class LoggerBase (val logCounter : LogCounter ) {
@@ -54,10 +84,6 @@ open class LoggerBase(val logCounter: LogCounter) {
54
84
}
55
85
}
56
86
57
- private fun timestamp (): String {
58
- return " [${SimpleDateFormat (" yyyy-MM-dd HH:mm:ss" ).format(Date ())} K]"
59
- }
60
-
61
87
private fun getDiagnosticLocation (): String? {
62
88
val st = Exception ().stackTrace
63
89
for (x in st) {
@@ -84,7 +110,6 @@ open class LoggerBase(val logCounter: LogCounter) {
84
110
fun diagnostic (tw : TrapWriter , severity : Severity , msg : String , extraInfo : String? , locationString : String? = null, mkLocationId : () -> Label <DbLocation > = { tw.unknownLocation }) {
85
111
val diagnosticLoc = getDiagnosticLocation()
86
112
val diagnosticLocStr = if (diagnosticLoc == null ) " <unknown location>" else diagnosticLoc
87
- val extraInfoStr = if (extraInfo == null ) " " else (extraInfo + " \n " )
88
113
val suffix =
89
114
if (diagnosticLoc == null ) {
90
115
" Missing caller information.\n "
@@ -100,8 +125,10 @@ open class LoggerBase(val logCounter: LogCounter) {
100
125
}
101
126
val fullMsgBuilder = StringBuilder ()
102
127
fullMsgBuilder.append(msg)
103
- fullMsgBuilder.append(' \n ' )
104
- fullMsgBuilder.append(extraInfoStr)
128
+ if (extraInfo != null ) {
129
+ fullMsgBuilder.append(' \n ' )
130
+ fullMsgBuilder.append(extraInfo)
131
+ }
105
132
106
133
val iter = extractorContextStack.listIterator(extractorContextStack.size)
107
134
while (iter.hasPrevious()) {
@@ -111,38 +138,38 @@ open class LoggerBase(val logCounter: LogCounter) {
111
138
fullMsgBuilder.append(suffix)
112
139
113
140
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 " )
115
144
// We don't actually make the location until after the `return` above
116
145
val locationId = mkLocationId()
117
146
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)
119
148
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())
123
150
}
124
151
125
152
fun trace (tw : TrapWriter , msg : String ) {
126
153
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() )
130
157
}
131
158
}
132
159
133
160
fun debug (tw : TrapWriter , msg : String ) {
134
161
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() )
138
165
}
139
166
}
140
167
141
168
fun info (tw : TrapWriter , msg : String ) {
142
169
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() )
146
173
}
147
174
}
148
175
@@ -160,9 +187,12 @@ open class LoggerBase(val logCounter: LogCounter) {
160
187
fun printLimitedDiagnosticCounts (tw : TrapWriter ) {
161
188
for ((caller, count) in logCounter.diagnosticCounts) {
162
189
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())
166
196
}
167
197
}
168
198
}
0 commit comments