1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-22 08:13:47 +00:00

basically add logging

This commit is contained in:
InsanusMokrassar 2023-11-23 12:47:58 +06:00
parent e34bc7453e
commit 816cf00dac
12 changed files with 73 additions and 9 deletions

View File

@ -14,6 +14,7 @@ ksp = "1.9.20-1.0.14"
kotlin-poet = "1.14.2" kotlin-poet = "1.14.2"
microutils = "0.20.14" microutils = "0.20.14"
kslog = "1.3.0"
versions = "0.50.0" versions = "0.50.0"
@ -54,6 +55,8 @@ microutils-languageCodes = { module = "dev.inmo:micro_utils.language_codes", ver
microutils-ktor-common = { module = "dev.inmo:micro_utils.ktor.common", version.ref = "microutils" } microutils-ktor-common = { module = "dev.inmo:micro_utils.ktor.common", version.ref = "microutils" }
microutils-fsm-common = { module = "dev.inmo:micro_utils.fsm.common", version.ref = "microutils" } microutils-fsm-common = { module = "dev.inmo:micro_utils.fsm.common", version.ref = "microutils" }
kslog = { module = "dev.inmo:kslog", version.ref = "kslog" }
# ksp dependencies # ksp dependencies
kotlin-poet = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin-poet" } kotlin-poet = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin-poet" }

View File

@ -31,6 +31,8 @@ kotlin {
api libs.microutils.languageCodes api libs.microutils.languageCodes
api libs.ktor.client.core api libs.ktor.client.core
api libs.kslog
} }
} }
commonTest { commonTest {

View File

@ -1,8 +1,10 @@
package dev.inmo.tgbotapi.bot.ktor package dev.inmo.tgbotapi.bot.ktor
import dev.inmo.kslog.common.KSLog
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import io.ktor.client.* import io.ktor.client.*
@ -22,6 +24,7 @@ expect class KtorRequestsExecutor internal constructor(
requestsLimiter: RequestLimiter, requestsLimiter: RequestLimiter,
jsonFormatter: Json, jsonFormatter: Json,
pipelineStepsHolder: KtorPipelineStepsHolder, pipelineStepsHolder: KtorPipelineStepsHolder,
logger: KSLog,
diff: Unit // just a diff property to know where constructor and where calling function with defaults diff: Unit // just a diff property to know where constructor and where calling function with defaults
) : BaseRequestsExecutor ) : BaseRequestsExecutor
@ -32,7 +35,8 @@ fun KtorRequestsExecutor(
excludeDefaultFactories: Boolean = false, excludeDefaultFactories: Boolean = false,
requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter, requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter,
jsonFormatter: Json = nonstrictJsonFormat, jsonFormatter: Json = nonstrictJsonFormat,
pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder,
logger: KSLog = DefaultKTgBotAPIKSLog,
) = KtorRequestsExecutor( ) = KtorRequestsExecutor(
telegramAPIUrlsKeeper = telegramAPIUrlsKeeper, telegramAPIUrlsKeeper = telegramAPIUrlsKeeper,
client = client, client = client,
@ -41,5 +45,6 @@ fun KtorRequestsExecutor(
requestsLimiter = requestsLimiter, requestsLimiter = requestsLimiter,
jsonFormatter = jsonFormatter, jsonFormatter = jsonFormatter,
pipelineStepsHolder = pipelineStepsHolder, pipelineStepsHolder = pipelineStepsHolder,
diff = kotlin.Unit logger = logger,
diff = kotlin.Unit,
) )

View File

@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.bot.ktor package dev.inmo.tgbotapi.bot.ktor
import dev.inmo.kslog.common.KSLog
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.ktor.base.* import dev.inmo.tgbotapi.bot.ktor.base.*
@ -25,6 +26,8 @@ class KtorRequestsExecutorBuilder(
var excludeDefaultFactories: Boolean = false var excludeDefaultFactories: Boolean = false
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter
var jsonFormatter: Json = nonstrictJsonFormat var jsonFormatter: Json = nonstrictJsonFormat
var logger: KSLog = DefaultKTgBotAPIKSLog
var pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder
fun build() = KtorRequestsExecutor( fun build() = KtorRequestsExecutor(
telegramAPIUrlsKeeper, telegramAPIUrlsKeeper,
@ -32,7 +35,9 @@ class KtorRequestsExecutorBuilder(
callsFactories, callsFactories,
excludeDefaultFactories, excludeDefaultFactories,
requestsLimiter, requestsLimiter,
jsonFormatter jsonFormatter,
pipelineStepsHolder,
logger
) )
} }

View File

@ -1,23 +1,30 @@
package dev.inmo.tgbotapi.bot.ktor.base package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.v
import dev.inmo.kslog.common.w
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.exceptions.newRequestException import dev.inmo.tgbotapi.bot.exceptions.newRequestException
import dev.inmo.tgbotapi.requests.GetUpdatesRequest import dev.inmo.tgbotapi.requests.GetUpdatesRequest
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.types.Response
import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.plugins.timeout import io.ktor.client.plugins.timeout
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.bodyAsText import io.ktor.client.statement.bodyAsText
import io.ktor.http.ContentType import io.ktor.http.ContentType
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.collections.set import kotlin.collections.set
var defaultUpdateTimeoutForZeroDelay = 1000L var defaultUpdateTimeoutForZeroDelay = 1000L
abstract class AbstractRequestCallFactory : KtorCallFactory { abstract class AbstractRequestCallFactory(
protected open val logger: KSLog = DefaultKTgBotAPIKSLog
) : KtorCallFactory {
private val methodsCache: MutableMap<String, String> = mutableMapOf() private val methodsCache: MutableMap<String, String> = mutableMapOf()
override suspend fun <T : Any> makeCall( override suspend fun <T : Any> makeCall(
client: HttpClient, client: HttpClient,
@ -26,6 +33,7 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
jsonFormatter: Json jsonFormatter: Json
): T? { ): T? {
val preparedBody = prepareCallBody(client, urlsKeeper, request) ?: return null val preparedBody = prepareCallBody(client, urlsKeeper, request) ?: return null
logger.v { "Prepared body for $request: $preparedBody" }
client.post { client.post {
url( url(
@ -54,7 +62,9 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
setBody(preparedBody) setBody(preparedBody)
}.let { response -> }.let { response ->
val content = response.bodyAsText() val content = response.bodyAsText()
logger.v { "Raw answer for $request: $content" }
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
logger.v { "Answer as json for $request: $responseObject" }
return runCatchingSafely { return runCatchingSafely {
(responseObject.result?.let { (responseObject.result?.let {
@ -66,6 +76,8 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
"Can't get result object from $content" "Can't get result object from $content"
) )
}) })
}.onFailure {
logger.w { "Got exception answer for $request: $it" }
}.getOrThrow() }.getOrThrow()
} }
} }

View File

@ -1,5 +1,9 @@
package dev.inmo.tgbotapi.bot.ktor.base package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.e
import dev.inmo.kslog.common.i
import dev.inmo.kslog.common.v
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.exceptions.BotException import dev.inmo.tgbotapi.bot.exceptions.BotException
@ -28,12 +32,15 @@ class DefaultKtorRequestsExecutor internal constructor(
private val requestsLimiter: RequestLimiter, private val requestsLimiter: RequestLimiter,
private val jsonFormatter: Json, private val jsonFormatter: Json,
private val pipelineStepsHolder: KtorPipelineStepsHolder, private val pipelineStepsHolder: KtorPipelineStepsHolder,
private val logger: KSLog,
diff: Unit diff: Unit
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { ) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val callsFactories: List<KtorCallFactory> = callsFactories.run { private val callsFactories: List<KtorCallFactory> = callsFactories.run {
if (!excludeDefaultFactories) { if (!excludeDefaultFactories) {
logger.v { "Installing default factories" }
this + createTelegramBotDefaultKtorCallRequestsFactories() this + createTelegramBotDefaultKtorCallRequestsFactories()
} else { } else {
logger.v { "Default factories will not be installed" }
this this
} }
} }
@ -46,19 +53,23 @@ class DefaultKtorRequestsExecutor internal constructor(
override suspend fun <T : Any> execute(request: Request<T>): T { override suspend fun <T : Any> execute(request: Request<T>): T {
return runCatchingSafely { return runCatchingSafely {
logger.v { "Start request $request" }
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories) pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
requestsLimiter.limit(request) { requestsLimiter.limit(request) {
var result: T? = null var result: T? = null
lateinit var factoryHandledRequest: KtorCallFactory lateinit var factoryHandledRequest: KtorCallFactory
for (potentialFactory in callsFactories) { for (potentialFactory in callsFactories) {
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory) pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
result = potentialFactory.makeCall( logger.v { "Trying factory $potentialFactory for $request" }
val resultFromFactory = potentialFactory.makeCall(
client, client,
telegramAPIUrlsKeeper, telegramAPIUrlsKeeper,
request, request,
jsonFormatter jsonFormatter
) )
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory) logger.v { "Result of factory $potentialFactory handling $request: $resultFromFactory" }
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(resultFromFactory, request, potentialFactory)
logger.v { "Result of pipeline $pipelineStepsHolder handling $resultFromFactory: $result" }
if (result != null) { if (result != null) {
factoryHandledRequest = potentialFactory factoryHandledRequest = potentialFactory
break break
@ -71,6 +82,7 @@ class DefaultKtorRequestsExecutor internal constructor(
} }
}.let { }.let {
val result = it.exceptionOrNull() ?.let { e -> val result = it.exceptionOrNull() ?.let { e ->
logger.v(e) { "Got exception on handling of $request" }
pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it } pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it }
when (e) { when (e) {
@ -90,9 +102,13 @@ class DefaultKtorRequestsExecutor internal constructor(
} }
is BotException -> e is BotException -> e
else -> CommonBotException(cause = e) else -> CommonBotException(cause = e)
}.also {
logger.v(e) { "Result exception on handling of $request: $it" }
} }
} ?.let { Result.failure(it) } ?: it } ?.let { Result.failure(it) } ?: it
pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories) pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories).also {
logger.v { "Result of handling $request: $it" }
}
} }
} }

View File

@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.DownloadFileStream import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.receive import io.ktor.client.call.receive
@ -15,6 +16,7 @@ import io.ktor.utils.io.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@RiskFeature
object DownloadFileChannelRequestCallFactory : KtorCallFactory { object DownloadFileChannelRequestCallFactory : KtorCallFactory {
override suspend fun <T : Any> makeCall( override suspend fun <T : Any> makeCall(
client: HttpClient, client: HttpClient,

View File

@ -4,12 +4,14 @@ import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.DownloadFile import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.client.statement.readBytes import io.ktor.client.statement.readBytes
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@RiskFeature
object DownloadFileRequestCallFactory : KtorCallFactory { object DownloadFileRequestCallFactory : KtorCallFactory {
override suspend fun <T : Any> makeCall( override suspend fun <T : Any> makeCall(
client: HttpClient, client: HttpClient,

View File

@ -1,6 +1,8 @@
package dev.inmo.tgbotapi.bot.ktor.base package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.kslog.common.KSLog
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.mapWithCommonValues import dev.inmo.tgbotapi.utils.mapWithCommonValues
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
@ -8,7 +10,7 @@ import io.ktor.client.request.forms.*
import io.ktor.http.Headers import io.ktor.http.Headers
import io.ktor.http.HttpHeaders import io.ktor.http.HttpHeaders
class MultipartRequestCallFactory : AbstractRequestCallFactory() { class MultipartRequestCallFactory(logger: KSLog? = null) : AbstractRequestCallFactory(logger ?: DefaultKTgBotAPIKSLog) {
override fun <T : Any> prepareCallBody( override fun <T : Any> prepareCallBody(
client: HttpClient, client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper, urlsKeeper: TelegramAPIUrlsKeeper,

View File

@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.bot.ktor.base package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.kslog.common.KSLog
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
@ -48,6 +49,7 @@ class MultipleClientKtorRequestsExecutor (
jsonFormatter: Json, jsonFormatter: Json,
pipelineStepsHolder: KtorPipelineStepsHolder, pipelineStepsHolder: KtorPipelineStepsHolder,
requestExecutorsCount: Int, requestExecutorsCount: Int,
logger: KSLog,
clientFactory: () -> HttpClient clientFactory: () -> HttpClient
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { ) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val requestExecutors = (0 until requestExecutorsCount).map { private val requestExecutors = (0 until requestExecutorsCount).map {
@ -59,6 +61,7 @@ class MultipleClientKtorRequestsExecutor (
requestsLimiter, requestsLimiter,
jsonFormatter, jsonFormatter,
pipelineStepsHolder, pipelineStepsHolder,
logger,
Unit Unit
) )
}.toSet() }.toSet()
@ -80,6 +83,7 @@ class MultipleClientKtorRequestsExecutor (
requestsLimiter: RequestLimiter, requestsLimiter: RequestLimiter,
jsonFormatter: Json, jsonFormatter: Json,
pipelineStepsHolder: KtorPipelineStepsHolder, pipelineStepsHolder: KtorPipelineStepsHolder,
logger: KSLog,
diff: Unit diff: Unit
) : this( ) : this(
telegramAPIUrlsKeeper, telegramAPIUrlsKeeper,
@ -89,6 +93,7 @@ class MultipleClientKtorRequestsExecutor (
jsonFormatter, jsonFormatter,
pipelineStepsHolder, pipelineStepsHolder,
client.engineConfig.threadsCount, client.engineConfig.threadsCount,
logger,
{ platformClientCopy(client) } { platformClientCopy(client) }
) )

View File

@ -1,12 +1,14 @@
package dev.inmo.tgbotapi.bot.ktor.base package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.kslog.common.KSLog
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.content.TextContent import io.ktor.http.content.TextContent
class SimpleRequestCallFactory : AbstractRequestCallFactory() { class SimpleRequestCallFactory(logger: KSLog? = null) : AbstractRequestCallFactory(logger ?: DefaultKTgBotAPIKSLog) {
override fun <T : Any> prepareCallBody( override fun <T : Any> prepareCallBody(
client: HttpClient, client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper, urlsKeeper: TelegramAPIUrlsKeeper,

View File

@ -0,0 +1,8 @@
package dev.inmo.tgbotapi.utils
import dev.inmo.kslog.common.KSLog
/**
* Default realization of [KSLog] which will be used everywhere where there is no some custom variant of [KSLog]
*/
var DefaultKTgBotAPIKSLog = KSLog("KTgBot")