Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: message logging
- the plugin was loading so no classloading issues related to logging classes, but it was not logging
  anything from the plugin.
- the tinylog dependency was apparently ignored. Until we receive a definitive answer from JetBrains
  we have two options: either propagate the service locator and the logging service to every component
  (even non UI models/views) or wrap the toolbox logging service in a slf4j implementation with minimal
  invasive changes.
- the latter approach is possible because no component is initialized until CoderToolboxExtension is called.
  That means we have the chance to initialize our custom logger factory around the toolbox logger service.
  • Loading branch information
fioan89 committed Feb 25, 2025
commit 500d3979d4a923f8a01a7d59eb1c17bc7c77b79f
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ jvmWrapper {
dependencies {
compileOnly(libs.bundles.toolbox.plugin.api)
implementation(libs.slf4j)
implementation(libs.tinylog)
implementation(libs.bundles.serialization)
implementation(libs.coroutines.core)
implementation(libs.okhttp)
Expand Down
2 changes: 0 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ coroutines = "1.10.1"
serialization = "1.8.0"
okhttp = "4.10.0"
slf4j = "2.0.3"
tinylog = "2.7.0"
dependency-license-report = "2.5"
marketplace-client = "2.0.38"
gradle-wrapper = "0.14.0"
Expand All @@ -24,7 +23,6 @@ serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-jso
serialization-json-okio = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-okio", version.ref = "serialization" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
tinylog = {module = "org.tinylog:slf4j-tinylog", version.ref = "tinylog"}
exec = { module = "org.zeroturnaround:zt-exec", version.ref = "exec" }
moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi"}
moshi-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi"}
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.coder.toolbox

import com.coder.toolbox.cli.CoderCLIManager
import com.coder.toolbox.logger.CoderLoggerFactory
import com.coder.toolbox.sdk.CoderRestClient
import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
import com.coder.toolbox.services.CoderSecretsService
Expand Down Expand Up @@ -34,7 +35,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import org.slf4j.LoggerFactory
import java.net.URI
import java.net.URL
import kotlin.coroutines.cancellation.CancellationException
Expand All @@ -44,7 +44,7 @@ class CoderRemoteProvider(
private val serviceLocator: ServiceLocator,
private val httpClient: OkHttpClient,
) : RemoteProvider("Coder") {
private val logger = LoggerFactory.getLogger(javaClass)
private val logger = CoderLoggerFactory.getLogger(javaClass)

private val ui: ToolboxUi = serviceLocator.getService(ToolboxUi::class.java)
private val consumer: RemoteEnvironmentConsumer = serviceLocator.getService(RemoteEnvironmentConsumer::class.java)
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/com/coder/toolbox/CoderToolboxExtension.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.coder.toolbox

import com.coder.toolbox.logger.CoderLoggerFactory
import com.jetbrains.toolbox.api.core.ServiceLocator
import com.jetbrains.toolbox.api.core.diagnostics.Logger
import com.jetbrains.toolbox.api.remoteDev.RemoteDevExtension
import com.jetbrains.toolbox.api.remoteDev.RemoteProvider
import okhttp3.OkHttpClient
Expand All @@ -11,6 +13,9 @@ import okhttp3.OkHttpClient
class CoderToolboxExtension : RemoteDevExtension {
// All services must be passed in here and threaded as necessary.
override fun createRemoteProviderPluginInstance(serviceLocator: ServiceLocator): RemoteProvider {
// initialize logger factory
CoderLoggerFactory.tLogger = serviceLocator.getService(Logger::class.java)

return CoderRemoteProvider(
serviceLocator,
OkHttpClient(),
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/coder/toolbox/cli/CoderCLIManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.coder.toolbox.cli
import com.coder.toolbox.cli.ex.MissingVersionException
import com.coder.toolbox.cli.ex.ResponseException
import com.coder.toolbox.cli.ex.SSHConfigFormatException
import com.coder.toolbox.logger.CoderLoggerFactory
import com.coder.toolbox.settings.CoderSettings
import com.coder.toolbox.settings.CoderSettingsState
import com.coder.toolbox.util.CoderHostnameVerifier
Expand All @@ -20,7 +21,6 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.JsonDataException
import com.squareup.moshi.Moshi
import org.slf4j.LoggerFactory
import org.zeroturnaround.exec.ProcessExecutor
import java.io.EOFException
import java.io.FileInputStream
Expand Down Expand Up @@ -126,7 +126,7 @@ class CoderCLIManager(
// manager to download to the data directory instead.
forceDownloadToData: Boolean = false,
) {
private val logger = LoggerFactory.getLogger(javaClass)
private val logger = CoderLoggerFactory.getLogger(javaClass)

val remoteBinaryURL: URL = settings.binSource(deploymentURL)
val localBinaryPath: Path = settings.binPath(deploymentURL, forceDownloadToData)
Expand Down
12 changes: 12 additions & 0 deletions src/main/kotlin/com/coder/toolbox/logger/CoderLoggerFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.coder.toolbox.logger

import org.slf4j.ILoggerFactory
import org.slf4j.Logger
import com.jetbrains.toolbox.api.core.diagnostics.Logger as ToolboxLogger

object CoderLoggerFactory : ILoggerFactory {
var tLogger: ToolboxLogger? = null

fun getLogger(clazz: Class<Any>): Logger = getLogger(clazz.name)
override fun getLogger(clazzName: String): Logger = LoggerImpl(clazzName, tLogger)
}
235 changes: 235 additions & 0 deletions src/main/kotlin/com/coder/toolbox/logger/LoggerImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package com.coder.toolbox.logger

import org.slf4j.Logger
import org.slf4j.Marker
import com.jetbrains.toolbox.api.core.diagnostics.Logger as ToolboxLogger

class LoggerImpl(private val clazzName: String, private val tLogger: ToolboxLogger?) : Logger {
override fun getName(): String = clazzName

override fun isTraceEnabled(): Boolean = true

override fun trace(message: String) {
tLogger?.trace(message)
}

override fun trace(message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.trace(it, message) } ?: tLogger?.trace(message)
}

override fun trace(message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.trace(it, message) } ?: tLogger?.trace(message)
}

override fun trace(message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.trace(it, message) } ?: tLogger?.trace(message)
}

override fun trace(message: String, exception: Throwable) {
tLogger?.trace(exception, message)
}

override fun isTraceEnabled(marker: Marker): Boolean = true

override fun trace(marker: Marker, message: String) {
tLogger?.trace(message)
}

override fun trace(marker: Marker, message: String, arg: Any) {
extractThrowable(arg)?.let { tLogger?.trace(it, message) } ?: tLogger?.trace(message)
}

override fun trace(marker: Marker, message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.trace(it, message) } ?: tLogger?.trace(message)
}

override fun trace(marker: Marker, message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.trace(it, message) } ?: tLogger?.trace(message)
}

override fun trace(marker: Marker, message: String, exception: Throwable) {
tLogger?.trace(exception, message)
}

override fun isDebugEnabled(): Boolean = true

override fun debug(message: String) {
tLogger?.debug(message)
}

override fun debug(message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.debug(it, message) } ?: tLogger?.debug(message)
}

override fun debug(message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.debug(it, message) } ?: tLogger?.debug(message)
}

override fun debug(message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.debug(it, message) } ?: tLogger?.debug(message)
}

override fun debug(message: String, exception: Throwable) {
tLogger?.debug(exception, message)
}

override fun isDebugEnabled(marker: Marker): Boolean = true

override fun debug(marker: Marker, message: String) {
tLogger?.debug(message)
}

override fun debug(marker: Marker, message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.debug(it, message) } ?: tLogger?.debug(message)
}

override fun debug(marker: Marker, message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.debug(it, message) } ?: tLogger?.debug(message)
}

override fun debug(marker: Marker, message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.debug(it, message) } ?: tLogger?.debug(message)
}

override fun debug(marker: Marker, message: String, exception: Throwable) {
tLogger?.debug(exception, message)
}

override fun isInfoEnabled(): Boolean = true

override fun info(message: String) {
tLogger?.info(message)
}

override fun info(message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.info(it, message) } ?: tLogger?.info(message)
}

override fun info(message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.info(it, message) } ?: tLogger?.info(message)
}

override fun info(message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.info(it, message) } ?: tLogger?.info(message)
}

override fun info(message: String, exception: Throwable) {
tLogger?.info(exception, message)
}

override fun isInfoEnabled(marker: Marker): Boolean = true

override fun info(marker: Marker, message: String) {
tLogger?.info(message)
}

override fun info(marker: Marker, message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.info(it, message) } ?: tLogger?.info(message)
}

override fun info(marker: Marker, message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.info(it, message) } ?: tLogger?.info(message)
}

override fun info(marker: Marker, message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.info(it, message) } ?: tLogger?.info(message)
}

override fun info(marker: Marker, message: String, exception: Throwable) {
tLogger?.info(exception, message)
}

override fun isWarnEnabled(): Boolean = true

override fun warn(message: String) {
tLogger?.warn(message)
}

override fun warn(message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.warn(it, message) } ?: tLogger?.warn(message)
}

override fun warn(message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.warn(it, message) } ?: tLogger?.warn(message)
}

override fun warn(message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.warn(it, message) } ?: tLogger?.warn(message)
}

override fun warn(message: String, exception: Throwable) {
tLogger?.warn(exception, message)
}

override fun isWarnEnabled(marker: Marker): Boolean = true

override fun warn(marker: Marker, message: String) {
tLogger?.warn(message)
}

override fun warn(marker: Marker, message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.warn(it, message) } ?: tLogger?.warn(message)
}

override fun warn(marker: Marker, message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.warn(it, message) } ?: tLogger?.warn(message)
}

override fun warn(marker: Marker, message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.warn(it, message) } ?: tLogger?.warn(message)
}

override fun warn(marker: Marker, message: String, exception: Throwable) {
tLogger?.warn(exception, message)
}

override fun isErrorEnabled(): Boolean = true

override fun error(message: String) {
tLogger?.error(message)
}

override fun error(message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.error(it, message) } ?: tLogger?.error(message)
}

override fun error(message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.error(it, message) } ?: tLogger?.error(message)
}

override fun error(message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.error(it, message) } ?: tLogger?.error(message)
}

override fun error(message: String, exception: Throwable) {
tLogger?.error(exception, message)
}

override fun isErrorEnabled(marker: Marker): Boolean = true

override fun error(marker: Marker, message: String) {
tLogger?.error(message)
}

override fun error(marker: Marker, message: String, arg: Any?) {
extractThrowable(arg)?.let { tLogger?.error(it, message) } ?: tLogger?.error(message)
}

override fun error(marker: Marker, message: String, firstArg: Any?, secondArg: Any?) {
extractThrowable(firstArg, secondArg)?.let { tLogger?.error(it, message) } ?: tLogger?.error(message)
}

override fun error(marker: Marker, message: String, vararg args: Any?) {
extractThrowable(args)?.let { tLogger?.error(it, message) } ?: tLogger?.error(message)
}

override fun error(marker: Marker, message: String, exception: Throwable) {
tLogger?.error(exception, message)
}

companion object {
fun extractThrowable(vararg args: Any?): Throwable? = args.firstOrNull { it is Throwable } as? Throwable

fun extractThrowable(arg: Any?): Throwable? = arg as? Throwable
}
}
4 changes: 2 additions & 2 deletions src/main/kotlin/com/coder/toolbox/settings/CoderSettings.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.coder.toolbox.settings

import com.coder.toolbox.logger.CoderLoggerFactory
import com.coder.toolbox.util.Arch
import com.coder.toolbox.util.OS
import com.coder.toolbox.util.expand
Expand All @@ -8,7 +9,6 @@ import com.coder.toolbox.util.getOS
import com.coder.toolbox.util.safeHost
import com.coder.toolbox.util.toURL
import com.coder.toolbox.util.withPath
import org.slf4j.LoggerFactory
import java.net.URL
import java.nio.file.Files
import java.nio.file.Path
Expand Down Expand Up @@ -127,7 +127,7 @@ open class CoderSettings(
// Overrides the default binary name (for tests).
private val binaryName: String? = null,
) {
private val logger = LoggerFactory.getLogger(javaClass)
private val logger = CoderLoggerFactory.getLogger(javaClass)

val tls = CoderTLSSettings(state)

Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/coder/toolbox/util/TLS.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.coder.toolbox.util

import com.coder.toolbox.logger.CoderLoggerFactory
import com.coder.toolbox.settings.CoderTLSSettings
import okhttp3.internal.tls.OkHostnameVerifier
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
import java.net.InetAddress
Expand Down Expand Up @@ -182,7 +182,7 @@ class AlternateNameSSLSocketFactory(private val delegate: SSLSocketFactory, priv
}

class CoderHostnameVerifier(private val alternateName: String) : HostnameVerifier {
private val logger = LoggerFactory.getLogger(javaClass)
private val logger = CoderLoggerFactory.getLogger(javaClass)

override fun verify(
host: String,
Expand Down
Loading