Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add more logging on testservice and possibility to set development api on instance creation #2225

Merged
merged 15 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ object CoreLogger {
CryptographyLogger.init(config = config)
PersistenceLogger.init(config = config)
}

fun setLoggingLevel(level: KaliumLogLevel) {
kaliumLoggerConfig.setLogLevel(level)
}
Expand Down
10 changes: 6 additions & 4 deletions testservice/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ logging:

# The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL.
level: INFO
loggers:
com.wire.kalium: DEBUG

appenders:
- type: console
threshold: INFO
threshold: DEBUG
- type: file
threshold: INFO
logFormat: "%-6level [%d{HH:mm:ss.SSS}] [%t] %logger{5} - %X{code} %msg %n"
threshold: DEBUG
logFormat: "%-6level [%d{HH:mm:ss.SSS}] %X{code} %msg %n"
currentLogFilename: /var/log/kalium-testservice/application.log
archivedLogFilenamePattern: /var/log/kalium-testservice/application-%d{yyyy-MM-dd}.log
archivedFileCount: 7
timeZone: GMT+1
- type: file
threshold: ALL
logFormat: "%-6level [%d{HH:mm:ss.SSS}] [%t] %logger{5} - %X{code} %msg %n"
logFormat: "%-6level [%d{HH:mm:ss.SSS}] %X{code} %msg %n"
currentLogFilename: /var/log/kalium-testservice/application_debug.log
archivedLogFilenamePattern: /var/log/kalium-testservice/application_debug-%d{yyyy-MM-dd}.log
archivedFileCount: 7
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.testservice

import co.touchlab.kermit.LogWriter
import co.touchlab.kermit.Severity
import com.wire.kalium.testservice.managed.InstanceService
import org.slf4j.LoggerFactory

class KaliumLogWriter(private val instanceId: String) : LogWriter() {

private val log = LoggerFactory.getLogger(InstanceService::class.java.name)

override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) {
when (severity) {
Severity.Verbose -> log.debug("Instance $instanceId: $message")
Severity.Debug -> log.debug("Instance $instanceId: $message")
Severity.Info -> log.info("Instance $instanceId: $message")
Severity.Warn -> log.warn("Instance $instanceId: $message")
Severity.Error -> log.error("Instance $instanceId: $message $throwable")
Severity.Assert -> log.info("Instance $instanceId: $message")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import javax.ws.rs.container.AsyncResponse
import javax.ws.rs.container.ConnectionCallback
import javax.ws.rs.container.Suspended
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("/api/v1")
@Produces(MediaType.APPLICATION_JSON)
Expand Down Expand Up @@ -69,14 +70,23 @@ class InstanceLifecycle(
// handles unresponsive instances
ar.setTimeout(timeout, TimeUnit.SECONDS)
ar.setTimeoutHandler { asyncResponse: AsyncResponse ->
log.error("Async create instance request timed out after $timeout seconds")
asyncResponse.cancel()
instanceService.deleteInstance(instanceId)
log.error("Instance $instanceId: Async create instance request timed out after $timeout seconds")
asyncResponse.resume(
Response
.status(Response.Status.GATEWAY_TIMEOUT)
.entity("Instance $instanceId: Async create instance request timed out after $timeout seconds")
.build()
)
if (instanceService.getInstance(instanceId) != null) {
instanceService.deleteInstance(instanceId)
}
}
// handles client disconnect
ar.register(ConnectionCallback { disconnected: AsyncResponse? ->
log.error("Client disconnected from async create instance request")
instanceService.deleteInstance(instanceId)
log.error("Instance $instanceId: Client disconnected from async create instance request")
if (instanceService.getInstance(instanceId) != null) {
instanceService.deleteInstance(instanceId)
}
})

val createdInstance = try {
Expand All @@ -86,7 +96,7 @@ class InstanceLifecycle(
} catch (we: WebApplicationException) {
throw we
} catch (e: Exception) {
log.error("Could not create instance: " + e.message, e)
log.error("Instance $instanceId: Could not create instance: " + e.message, e)
throw WebApplicationException("Could not create instance: " + e.message)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package com.wire.kalium.testservice.managed
import com.codahale.metrics.Gauge
import com.codahale.metrics.MetricRegistry
import com.wire.kalium.logger.KaliumLogLevel
import com.wire.kalium.logger.KaliumLogger
import com.wire.kalium.logic.CoreLogger
import com.wire.kalium.logic.CoreLogic
import com.wire.kalium.logic.configuration.server.ServerConfig
Expand All @@ -39,6 +40,7 @@ import com.wire.kalium.logic.feature.client.RegisterClientUseCase
import com.wire.kalium.logic.feature.session.CurrentSessionResult
import com.wire.kalium.logic.featureFlags.KaliumConfigs
import com.wire.kalium.logic.functional.onFailure
import com.wire.kalium.testservice.KaliumLogWriter
import com.wire.kalium.testservice.TestserviceConfiguration
import com.wire.kalium.testservice.models.FingerprintResponse
import com.wire.kalium.testservice.models.Instance
Expand Down Expand Up @@ -134,18 +136,18 @@ class InstanceService(
)
}

@Suppress("LongMethod", "ThrowsCount")
suspend fun createInstance(instanceId: String, instanceRequest: InstanceRequest): Instance {
@Suppress("LongMethod", "ThrowsCount", "ComplexMethod")
suspend fun createInstance(instanceId: String, instanceRequest: InstanceRequest): Any {
val userAgent = "KaliumTestService/${System.getProperty("http.agent")}"
val before = System.currentTimeMillis()
val instancePath = System.getProperty("user.home") +
File.separator + ".testservice" + File.separator + instanceId
log.info("Instance $instanceId: Creating $instancePath")
val kaliumConfigs = KaliumConfigs(
developmentApiEnabled = false
developmentApiEnabled = instanceRequest.developmentApiEnabled ?: false
)
val coreLogic = CoreLogic(instancePath, kaliumConfigs, userAgent)
CoreLogger.setLoggingLevel(KaliumLogLevel.VERBOSE)
CoreLogger.init(KaliumLogger.Config(KaliumLogLevel.VERBOSE, listOf(KaliumLogWriter(instanceId))))

val serverConfig = if (instanceRequest.customBackend != null) {
ServerConfig.Links(
Expand Down Expand Up @@ -208,10 +210,8 @@ class InstanceService(
loginResult.authData.userId
}

var clientId: String? = null

log.info("Instance $instanceId: Register client device")
runBlocking {
val response = runBlocking {
coreLogic.sessionScope(userId) {
if (client.needsToRegisterClient()) {
when (val result = client.getOrRegister(
Expand All @@ -222,33 +222,50 @@ class InstanceService(
model = instanceRequest.deviceName
)
)) {
is RegisterClientResult.Failure ->
throw WebApplicationException("Instance $instanceId: Client registration failed")

is RegisterClientResult.Success -> {
clientId = result.client.id.value
val clientId = result.client.id.value
log.info("Instance $instanceId: Device $clientId successfully registered")
syncManager.waitUntilLive()

val startTime = System.currentTimeMillis()
val startupTime = startTime - before

val instance = Instance(
instanceRequest.backend,
clientId,
instanceId,
instanceRequest.name,
coreLogic,
instancePath,
instanceRequest.password,
startupTime,
startTime
)
instances.put(instanceId, instance)

syncManager.waitUntilLiveOrFailure().onFailure {
log.error("Instance $instanceId: Sync failed with $it")
}

return@runBlocking instance
}
is RegisterClientResult.Failure.TooManyClients ->
throw WebApplicationException("Instance $instanceId: Client registration failed, too many clients")
is RegisterClientResult.Failure.InvalidCredentials.Invalid2FA ->
throw WebApplicationException("Instance $instanceId: Client registration failed, invalid 2FA code")
is RegisterClientResult.Failure.InvalidCredentials.InvalidPassword ->
throw WebApplicationException("Instance $instanceId: Client registration failed, invalid password")
is RegisterClientResult.Failure.InvalidCredentials.Missing2FA ->
throw WebApplicationException("Instance $instanceId: Client registration failed, 2FA code needed for account")
is RegisterClientResult.Failure.PasswordAuthRequired ->
throw WebApplicationException("Instance $instanceId: Client registration failed, missing password")
is RegisterClientResult.Failure.Generic ->
throw WebApplicationException("Instance $instanceId: Client registration failed")
}
}
}
}

val instance = Instance(
instanceRequest.backend,
clientId,
instanceId,
instanceRequest.name,
coreLogic,
instancePath,
instanceRequest.password,
System.currentTimeMillis() - before,
System.currentTimeMillis()
)
instances.put(instanceId, instance)

return instance
return response
}

fun deleteInstance(id: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ data class InstanceRequest(
val name: String = "",
val password: String = "",
val verificationCode: String? = null,
val developmentApiEnabled: Boolean? = false,
)
Loading