Allow bot owner to print debug stats

This commit is contained in:
kageru 2019-06-15 14:15:34 +02:00
parent f0db8b5c26
commit d662784d86
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
9 changed files with 137 additions and 6 deletions

View File

@ -3,9 +3,11 @@ package moe.kageru.kagebot
import moe.kageru.kagebot.config.Config
import org.javacord.api.DiscordApi
import org.javacord.api.entity.server.Server
import java.util.concurrent.atomic.AtomicInteger
object Globals {
lateinit var server: Server
lateinit var api: DiscordApi
lateinit var config: Config
var commandCounter: AtomicInteger = AtomicInteger(0)
}

View File

@ -67,5 +67,12 @@ object Kagebot {
}
}
}
Globals.config.features.debug?.let { debug ->
if (debug.enabled) {
Globals.api.addMessageCreateListener {
checked { debug.handle(it) }
}
}
}
}
}

View File

@ -1,5 +1,6 @@
package moe.kageru.kagebot.command
import moe.kageru.kagebot.Globals
import moe.kageru.kagebot.Globals.config
import moe.kageru.kagebot.MessageUtil
import moe.kageru.kagebot.Util.doIf
@ -36,6 +37,7 @@ class Command(cmd: RawCommand) {
}
return
}
Globals.commandCounter.incrementAndGet()
this.actions?.run(message, this)
this.response?.let {
message.channel.sendMessage(respond(message.messageAuthor, it))

View File

@ -42,10 +42,11 @@ class RawCommand(
class RawPermissions(val hasOneOf: List<String>?, val hasNoneOf: List<String>?, val onlyDM: Boolean)
class RawMessageActions(val delete: Boolean, val redirect: RawRedirect?)
class RawRedirect(val target: String?, val anonymous: Boolean)
class RawFeatures(val welcome: RawWelcomeFeature?)
class RawFeatures(val welcome: RawWelcomeFeature?, val debug: RawDebugFeatures?)
class RawWelcomeFeature(
val enabled: Boolean,
val content: Map<String, String>?,
val fallbackChannel: String?,
val fallbackMessage: String?
)
)
class RawDebugFeatures(var enabled: Boolean)

View File

@ -0,0 +1,77 @@
package moe.kageru.kagebot.features
import com.sun.management.OperatingSystemMXBean
import moe.kageru.kagebot.Globals
import moe.kageru.kagebot.MessageUtil
import moe.kageru.kagebot.config.RawDebugFeatures
import org.javacord.api.entity.message.embed.EmbedBuilder
import org.javacord.api.event.message.MessageCreateEvent
import java.lang.management.ManagementFactory
import java.time.Duration
import java.time.temporal.ChronoUnit
class DebugFeatures(rawDebugFeatures: RawDebugFeatures) {
fun handle(message: MessageCreateEvent) {
if (message.messageAuthor.isBotOwner) {
if (message.readableMessageContent.startsWith("!debugstats")) {
message.channel.sendMessage(getPerformanceStats())
}
}
}
private fun getPerformanceStats(): EmbedBuilder {
val osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean::class.java)
val runtime = Runtime.getRuntime()
return MessageUtil.mapToEmbed(
mapOf(
Pair(
"Bot:",
getBotStats()
),
Pair(
"Memory:",
getMemoryInfo(runtime, osBean)
),
Pair(
"CPU:",
getCpuInfo(osBean)
),
Pair(
"System:",
getOsInfo()
)
)
)
}
private fun getBotStats() = "kagebot has been running for ${getBotUptime()}.\n" +
"During this time, ${Globals.commandCounter.incrementAndGet()} commands have been executed."
private fun getBotUptime(): String {
val uptime = Duration.of(ManagementFactory.getRuntimeMXBean().uptime, ChronoUnit.MILLIS)
return String.format(
"%d days, %d hours, %d minutes, %d seconds",
uptime.toDaysPart(),
uptime.toHoursPart(),
uptime.toMinutesPart(),
uptime.toSecondsPart()
)
}
private fun getMemoryInfo(runtime: Runtime, osBean: OperatingSystemMXBean): String {
val mb = 1024 * 1024
return "Memory usage: ${(runtime.totalMemory() - runtime.freeMemory()) / mb} MB.\n" +
"Total system memory: ${osBean.committedVirtualMemorySize / mb}/" +
"${osBean.totalPhysicalMemorySize / mb} MB."
}
private fun getCpuInfo(osBean: OperatingSystemMXBean) =
"The bot is currently using ${String.format("%.4f", osBean.processCpuLoad * 100)}% of the CPU with " +
"${Thread.activeCount()} active threads.\n" +
"Total system load is ${String.format("%.2f", osBean.systemCpuLoad * 100)}%."
private fun getOsInfo() = "Running on ${System.getProperty("os.name")} " +
"${System.getProperty("os.version")}-${System.getProperty("os.arch")}.\n"
val enabled: Boolean = rawDebugFeatures.enabled
}

View File

@ -2,11 +2,14 @@ package moe.kageru.kagebot.features
import moe.kageru.kagebot.config.RawFeatures
class Features(val welcome: WelcomeFeature?) {
class Features(val welcome: WelcomeFeature?, val debug: DebugFeatures?) {
constructor(rawFeatures: RawFeatures) : this(rawFeatures.welcome?.let(::WelcomeFeature))
constructor(rawFeatures: RawFeatures) : this(
rawFeatures.welcome?.let(::WelcomeFeature),
rawFeatures.debug?.let(::DebugFeatures)
)
companion object {
val NONE = Features(null)
val NONE = Features(null, null)
}
}

View File

@ -22,6 +22,10 @@ fallbackMessage = "@@ I would like to greet you, but I can’t. :("
"Welcome to the Server" = "This is the content of the first paragraph"
"Second paragraph heading" = "Second paragraph content"
# allow the bot owner to get debug stats
[feature.debug]
enabled = true
[[command]]
trigger = "!ping"
response = "pong"

View File

@ -0,0 +1,32 @@
package moe.kageru.kagebot.features
import io.kotlintest.specs.StringSpec
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import moe.kageru.kagebot.TestUtil
import moe.kageru.kagebot.config.RawDebugFeatures
import org.javacord.api.entity.message.embed.EmbedBuilder
import org.javacord.api.event.message.MessageCreateEvent
class DebugFeatureTest : StringSpec({
TestUtil.prepareTestEnvironment()
// this will fail if the bot tries to execute more than it should
// because the mock does not provide the necessary methods
"should ignore regular users" {
val message = mockk<MessageCreateEvent> {
every { messageAuthor.isBotOwner } returns false
}
DebugFeatures(RawDebugFeatures(true)).handle(message)
verify(exactly = 0) { message.channel.sendMessage(any<EmbedBuilder>()) }
}
"should return something" {
val message = mockk<MessageCreateEvent> {
every { messageAuthor.isBotOwner } returns true
every { readableMessageContent } returns "!debugstats something"
every { channel.sendMessage(any<EmbedBuilder>()) } returns mockk()
}
DebugFeatures(RawDebugFeatures(true)).handle(message)
verify(exactly = 1) { message.channel.sendMessage(any<EmbedBuilder>()) }
}
})

View File

@ -1,9 +1,12 @@
package moe.kageru.kagebot
package moe.kageru.kagebot.features
import io.kotlintest.shouldBe
import io.kotlintest.specs.StringSpec
import io.mockk.every
import io.mockk.mockk
import moe.kageru.kagebot.Globals
import moe.kageru.kagebot.Kagebot
import moe.kageru.kagebot.TestUtil
import org.javacord.api.entity.message.embed.EmbedBuilder
class WelcomeFeatureTest : StringSpec({