Skip to content

Commit 2387d91

Browse files
committed
feat: add tcpDebug option and tracing log support
1 parent dc24041 commit 2387d91

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

server/build.gradle.kts

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ plugins {
99
id("kotlin-language-server.kotlin-conventions")
1010
}
1111

12+
val serverDebugPort = 4000
1213
val debugPort = 8000
13-
val debugArgs = "-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n,quiet=y"
14+
val debugArgs = "-agentlib:jdwp=transport=dt_socket,server=y,address=$debugPort,suspend=n,quiet=y"
1415

1516
val serverMainClassName = "org.javacs.kt.MainKt"
1617
val applicationName = "kotlin-language-server"
@@ -88,6 +89,8 @@ tasks.register<JavaExec>("debugRun") {
8889
standardInput = System.`in`
8990

9091
jvmArgs(debugArgs)
92+
args(listOf("--tcpServerPort", serverDebugPort, "--level", "trace", "--tcpDebug"))
93+
9194
doLast { println("Using debug port $debugPort") }
9295
}
9396

server/src/main/kotlin/org/javacs/kt/KotlinLanguageServer.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import java.util.concurrent.CompletableFuture
2323
import java.util.concurrent.CompletableFuture.completedFuture
2424

2525
class KotlinLanguageServer(
26-
val config: Configuration = Configuration()
26+
val config: Configuration = Configuration(),
27+
private val tcpDebug: Boolean = false
2728
) : LanguageServer, LanguageClientAware, Closeable {
2829
val databaseService = DatabaseService()
2930
val classPath = CompilerClassPath(config.compiler, config.scripts, config.codegen, databaseService)
@@ -56,7 +57,9 @@ class KotlinLanguageServer(
5657

5758
override fun connect(client: LanguageClient) {
5859
this.client = client
59-
connectLoggingBackend()
60+
if (!tcpDebug) {
61+
connectLoggingBackend()
62+
}
6063

6164
workspaces.connect(client)
6265
textDocuments.connect(client)

server/src/main/kotlin/org/javacs/kt/Main.kt

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,27 @@ import org.eclipse.lsp4j.launch.LSPLauncher
77
import org.javacs.kt.util.ExitingInputStream
88
import org.javacs.kt.util.tcpStartServer
99
import org.javacs.kt.util.tcpConnectToClient
10-
1110
class Args {
1211
/*
1312
* The language server can currently be launched in three modes:
1413
* - Stdio, in which case no argument should be specified (used by default)
1514
* - TCP Server, in which case the client has to connect to the specified tcpServerPort (used by the Docker image)
1615
* - TCP Client, in which case the server will connect to the specified tcpClientPort/tcpClientHost (optionally used by VSCode)
1716
*/
18-
1917
@Parameter(names = ["--tcpServerPort", "-sp"])
2018
var tcpServerPort: Int? = null
19+
2120
@Parameter(names = ["--tcpClientPort", "-p"])
2221
var tcpClientPort: Int? = null
22+
2323
@Parameter(names = ["--tcpClientHost", "-h"])
2424
var tcpClientHost: String = "localhost"
25+
26+
@Parameter(names = ["--level"])
27+
var logLevel: String = "info"
28+
29+
@Parameter(names = ["--tcpDebug"])
30+
var tcpDebug: Boolean = false
2531
}
2632

2733
fun main(argv: Array<String>) {
@@ -39,7 +45,8 @@ fun main(argv: Array<String>) {
3945
tcpStartServer(it)
4046
} ?: Pair(System.`in`, System.out)
4147

42-
val server = KotlinLanguageServer()
48+
LOG.setLogLevel(args.logLevel)
49+
val server = KotlinLanguageServer(tcpDebug = args.tcpDebug)
4350
val threads = Executors.newSingleThreadExecutor { Thread(it, "client") }
4451
val launcher = LSPLauncher.createServerLauncher(server, ExitingInputStream(inStream), outStream, threads) { it }
4552

shared/src/main/kotlin/org/javacs/kt/Logger.kt

+35-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import org.javacs.kt.util.DelegatePrintStream
1212

1313
val LOG = Logger()
1414

15-
private class JULRedirector(private val downstream: Logger): Handler() {
15+
private class JULRedirector(private val downstream: Logger) : Handler() {
1616
override fun publish(record: LogRecord) {
1717
when (record.level) {
1818
Level.SEVERE -> downstream.error(record.message)
@@ -41,12 +41,23 @@ enum class LogLevel(val value: Int) {
4141
ALL(-100)
4242
}
4343

44+
fun String.toLogLevel(): LogLevel {
45+
return when (this) {
46+
"error" -> LogLevel.ERROR
47+
"warn" -> LogLevel.WARN
48+
"debug" -> LogLevel.DEBUG
49+
"trace" -> LogLevel.TRACE
50+
else -> LogLevel.INFO
51+
}
52+
}
53+
4454
class LogMessage(
4555
val level: LogLevel,
46-
val message: String
56+
val message: String,
57+
private val funName: String? = null,
4758
) {
4859
val formatted: String
49-
get() = "[$level] $message"
60+
get() = "[$level] ${funName?.let { "$it " } ?: ""}$message"
5061
}
5162

5263
class Logger {
@@ -60,6 +71,7 @@ class Logger {
6071
private val newline = System.lineSeparator()
6172
val logTime = false
6273
var level = LogLevel.INFO
74+
var stackTracing = false;
6375

6476
fun logError(msg: LogMessage) {
6577
if (errBackend == null) {
@@ -78,14 +90,24 @@ class Logger {
7890
}
7991

8092
private fun logWithPlaceholdersAt(msgLevel: LogLevel, msg: String, placeholders: Array<out Any?>) {
93+
val stackTraceElement = if (stackTracing) {
94+
Throwable("Capturing stack trace for logging").stackTrace.firstOrNull { it.className != this::class.java.name }
95+
} else {
96+
null
97+
}
8198
if (level.value <= msgLevel.value) {
82-
log(LogMessage(msgLevel, format(insertPlaceholders(msg, placeholders))))
99+
log(LogMessage(msgLevel, format(insertPlaceholders(msg, placeholders)), stackTraceElement?.className))
83100
}
84101
}
85102

86103
inline fun logWithLambdaAt(msgLevel: LogLevel, msg: () -> String) {
104+
val stackTraceElement = if (stackTracing) {
105+
Throwable("Capturing stack trace for logging").stackTrace.firstOrNull { it.className != this::class.java.name }
106+
} else {
107+
null
108+
}
87109
if (level.value <= msgLevel.value) {
88-
log(LogMessage(msgLevel, msg()))
110+
log(LogMessage(msgLevel, msg(), stackTraceElement?.className))
89111
}
90112
}
91113

@@ -119,6 +141,14 @@ class Logger {
119141

120142
inline fun deepTrace(msg: () -> String) = logWithLambdaAt(LogLevel.DEEP_TRACE, msg)
121143

144+
fun setLogLevel(level: String) {
145+
val logLevel = level.toLogLevel()
146+
if (logLevel.value <= LogLevel.TRACE.value) {
147+
stackTracing = true
148+
}
149+
this.level = logLevel
150+
}
151+
122152
fun connectJULFrontend() {
123153
val rootLogger = java.util.logging.Logger.getLogger("")
124154
rootLogger.addHandler(JULRedirector(this))

0 commit comments

Comments
 (0)