Kotlin: Log to a file, not stdout

We shouldn't interfere with a build's stdout
This commit is contained in:
Ian Lynagh
2022-02-28 17:48:45 +00:00
parent a112e9ab5c
commit af7d809b8a
4 changed files with 61 additions and 30 deletions

View File

@@ -40,7 +40,7 @@ class ExternalClassExtractor(val logger: FileLogger, val invocationTrapFile: Str
GZIPOutputStream(trapTmpFile.outputStream()).bufferedWriter().use { trapFileBW ->
// We want our comments to be the first thing in the file,
// so start off with a mere TrapWriter
val tw = TrapWriter(logger, TrapLabelManager(), trapFileBW)
val tw = TrapWriter(logger.loggerBase, TrapLabelManager(), trapFileBW)
tw.writeComment("Generated by the CodeQL Kotlin extractor for external dependencies")
tw.writeComment("Part of invocation $invocationTrapFile")
// Now elevate to a SourceFileTrapWriter, and populate the

View File

@@ -83,7 +83,7 @@ class KotlinExtractorExtension(
tw.writeCompilation_compiler_times(compilation, -1.0, (System.currentTimeMillis()-compilationStartTime)/1000.0)
}
tw.flush()
val logger = Logger(logCounter, tw)
val logger = Logger(loggerBase, tw)
logger.info("Extraction started")
logger.flush()
if (System.getenv("CODEQL_EXTRACTOR_JAVA_KOTLIN_DUMP") == "true") {
@@ -100,15 +100,16 @@ class KotlinExtractorExtension(
val fileExtractionProblems = FileExtractionProblems(invocationExtractionProblems)
val fileTrapWriter = tw.makeSourceFileTrapWriter(file, true)
fileTrapWriter.writeCompilation_compiling_files(compilation, index, fileTrapWriter.fileId)
doFile(fileExtractionProblems, invocationTrapFile, fileTrapWriter, checkTrapIdentical, logCounter, trapDir, srcDir, file, primitiveTypeMapping, pluginContext, globalExtensionState)
doFile(fileExtractionProblems, invocationTrapFile, fileTrapWriter, checkTrapIdentical, loggerBase, trapDir, srcDir, file, primitiveTypeMapping, pluginContext, globalExtensionState)
fileTrapWriter.writeCompilation_compiling_files_completed(compilation, index, fileExtractionProblems.extractionResult())
}
logger.printLimitedDiagnosticCounts()
loggerBase.printLimitedDiagnosticCounts(tw)
logger.info("Extraction completed")
logger.flush()
val compilationTimeMs = System.currentTimeMillis() - startTimeMs
tw.writeCompilation_finished(compilation, -1.0, compilationTimeMs.toDouble() / 1000, invocationExtractionProblems.extractionResult())
tw.flush()
loggerBase.close()
}
}
}
@@ -198,7 +199,7 @@ private fun doFile(
invocationTrapFile: String,
fileTrapWriter: FileTrapWriter,
checkTrapIdentical: Boolean,
logCounter: LogCounter,
loggerBase: LoggerBase,
dbTrapDir: File,
dbSrcDir: File,
srcFile: IrFile,
@@ -206,7 +207,7 @@ private fun doFile(
pluginContext: IrPluginContext,
globalExtensionState: KotlinExtractorGlobalState) {
val srcFilePath = srcFile.path
val logger = FileLogger(logCounter, fileTrapWriter)
val logger = FileLogger(loggerBase, fileTrapWriter)
logger.info("Extracting file $srcFilePath")
logger.flush()
@@ -230,7 +231,7 @@ private fun doFile(
trapTmpFile.bufferedWriter().use { trapFileBW ->
// We want our comments to be the first thing in the file,
// so start off with a mere TrapWriter
val tw = TrapWriter(logger, TrapLabelManager(), trapFileBW)
val tw = TrapWriter(loggerBase, TrapLabelManager(), trapFileBW)
tw.writeComment("Generated by the CodeQL Kotlin extractor for kotlin source code")
tw.writeComment("Part of invocation $invocationTrapFile")
// Now elevate to a SourceFileTrapWriter, and populate the

View File

@@ -123,7 +123,7 @@ open class KotlinUsesExtractor(
if (isExternalDeclaration(cls) || clsFile == null) {
val filePath = getIrClassBinaryPath(cls)
val newTrapWriter = tw.makeFileTrapWriter(filePath, false)
val newLogger = FileLogger(logger.logCounter, newTrapWriter)
val newLogger = FileLogger(logger.loggerBase, newTrapWriter)
return KotlinFileExtractor(newLogger, newTrapWriter, filePath, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, globalExtensionState)
}
@@ -132,7 +132,7 @@ open class KotlinUsesExtractor(
}
val newTrapWriter = tw.makeSourceFileTrapWriter(clsFile, false)
val newLogger = FileLogger(logger.logCounter, newTrapWriter)
val newLogger = FileLogger(logger.loggerBase, newTrapWriter)
return KotlinFileExtractor(newLogger, newTrapWriter, clsFile.path, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, globalExtensionState)
}

View File

@@ -1,5 +1,9 @@
package com.github.codeql
import java.io.File
import java.io.FileWriter
import java.io.OutputStreamWriter
import java.io.Writer
import java.text.SimpleDateFormat
import java.util.Date
import org.jetbrains.kotlin.ir.IrElement
@@ -29,7 +33,18 @@ enum class Severity(val sev: Int) {
}
open class LoggerBase(val logCounter: LogCounter) {
protected fun timestamp(): String {
private val logStream: Writer
init {
val extractorLogDir = System.getenv("CODEQL_EXTRACTOR_JAVA_LOG_DIR")
if (extractorLogDir == null || extractorLogDir == "") {
logStream = OutputStreamWriter(System.out)
} else {
val logFile = File.createTempFile("kotlin-extractor.", ".log", File(extractorLogDir))
logStream = FileWriter(logFile)
}
}
private fun timestamp(): String {
return "[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())} K]"
}
@@ -70,7 +85,13 @@ open class LoggerBase(val logCounter: LogCounter) {
val locationId = mkLocationId()
tw.writeDiagnostics(StarLabel(), "CodeQL Kotlin extractor", severity.sev, "", msg, "$ts $fullMsg", locationId)
val locStr = if (locationString == null) "" else "At " + locationString + ": "
print("$ts Diagnostic($diagnosticLocStr): $locStr$fullMsg")
logStream.write("$ts Diagnostic($diagnosticLocStr): $locStr$fullMsg")
}
fun info(tw: TrapWriter, msg: String) {
val fullMsg = "${timestamp()} $msg"
tw.writeComment(fullMsg)
logStream.write(fullMsg + "\n")
}
fun warn(tw: TrapWriter, msg: String, extraInfo: String?) {
@@ -79,9 +100,27 @@ open class LoggerBase(val logCounter: LogCounter) {
fun error(tw: TrapWriter, msg: String, extraInfo: String?) {
diagnostic(tw, Severity.Error, msg, extraInfo)
}
fun printLimitedDiagnosticCounts(tw: TrapWriter) {
for((caller, count) in logCounter.diagnosticCounts) {
if(count >= logCounter.diagnosticLimit) {
val msg = "Total of $count diagnostics from $caller.\n"
tw.writeComment(msg)
logStream.write(msg)
}
}
}
fun flush() {
logStream.flush()
}
fun close() {
logStream.close()
}
}
open class Logger(logCounter: LogCounter, open val tw: TrapWriter): LoggerBase(logCounter) {
open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
private fun getDiagnosticLocation(): String? {
val st = Exception().stackTrace
for(x in st) {
@@ -98,13 +137,11 @@ open class Logger(logCounter: LogCounter, open val tw: TrapWriter): LoggerBase(l
fun flush() {
tw.flush()
System.out.flush()
loggerBase.flush()
}
fun info(msg: String) {
val fullMsg = "${timestamp()} $msg"
tw.writeComment(fullMsg)
println(fullMsg)
loggerBase.info(tw, msg)
}
fun trace(msg: String) {
if(false) {
@@ -117,17 +154,19 @@ open class Logger(logCounter: LogCounter, open val tw: TrapWriter): LoggerBase(l
fun trace(msg: String, exn: Exception) {
trace(msg + "\n" + exn.stackTraceToString())
}
fun warn(msg: String, exn: Exception) {
warn(msg, exn.stackTraceToString())
}
fun warn(msg: String, extraInfo: String?) {
warn(tw, msg, extraInfo)
loggerBase.warn(tw, msg, extraInfo)
}
fun warn(msg: String) {
warn(msg, null)
}
fun error(msg: String, extraInfo: String?) {
error(tw, msg, extraInfo)
loggerBase.error(tw, msg, extraInfo)
}
fun error(msg: String) {
error(msg, null)
@@ -135,27 +174,18 @@ open class Logger(logCounter: LogCounter, open val tw: TrapWriter): LoggerBase(l
fun error(msg: String, exn: Exception) {
error(msg, exn.stackTraceToString())
}
fun printLimitedDiagnosticCounts() {
for((caller, count) in logCounter.diagnosticCounts) {
if(count >= logCounter.diagnosticLimit) {
val msg = "Total of $count diagnostics from $caller.\n"
tw.writeComment(msg)
print(msg)
}
}
}
}
class FileLogger(logCounter: LogCounter, override val tw: FileTrapWriter): Logger(logCounter, tw) {
class FileLogger(loggerBase: LoggerBase, override val tw: FileTrapWriter): Logger(loggerBase, tw) {
fun warnElement(msg: String, element: IrElement) {
val locationString = tw.getLocationString(element)
val mkLocationId = { tw.getLocation(element) }
diagnostic(tw, Severity.Warn, msg, null, locationString, mkLocationId)
loggerBase.diagnostic(tw, Severity.Warn, msg, null, locationString, mkLocationId)
}
fun errorElement(msg: String, element: IrElement) {
val locationString = tw.getLocationString(element)
val mkLocationId = { tw.getLocation(element) }
diagnostic(tw, Severity.Error, msg, null, locationString, mkLocationId)
loggerBase.diagnostic(tw, Severity.Error, msg, null, locationString, mkLocationId)
}
}