new logger level and formatter

- add MornyLogLevels with new log level NOTICE(notice) and ATTION(attention)
  - make mechanic and morny (but not coeur) related INFO to NOTICE, warn to ATTION
- add MornyFormatterConsole to support the formatted time display, and some other formatter changed
- now startup key output will hide key except the starting and ending 4 chars
- change the function definition of consume in EventEnv
- removed src/test/scala/live/LiveMain
  - and added gitignore for src/test/scala/live
This commit is contained in:
A.C.Sukazyo Eyre 2023-10-15 21:14:54 +08:00
parent 9c433ba0ab
commit 79206dd13b
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
18 changed files with 116 additions and 52 deletions

View File

@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur
MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
VERSION = 1.1.1.xiongan-dev1
VERSION = 1.1.1.xiongan-dev2
USE_DELTA = false
VERSION_DELTA =
@ -17,7 +17,7 @@ CODENAME = nanchang
lib_spotbugs_v = 4.7.3
lib_scalamodule_xml_v = 2.2.0
lib_messiva_v = 0.1.1
lib_messiva_v = 0.2.0
lib_resourcetools_v = 0.2.2
lib_javatelegramapi_v = 6.2.0

View File

@ -1,2 +1,2 @@
rootProject.name = 'Coeur Morny Cono'
rootProject.name = "Coeur Morny Cono"

View File

@ -1,25 +1,27 @@
package cc.sukazyo.cono.morny
import cc.sukazyo.cono.morny.internal.logging.{MornyFormatterConsole, MornyLoggerBase}
import cc.sukazyo.messiva.appender.ConsoleAppender
import cc.sukazyo.messiva.formatter.SimpleFormatter
import cc.sukazyo.messiva.log.LogLevel
import cc.sukazyo.messiva.log.LogLevels
import cc.sukazyo.messiva.logger.Logger
import java.io.{PrintWriter, StringWriter}
object Log {
val logger: Logger = Logger(
val logger: MornyLoggerBase = MornyLoggerBase(
ConsoleAppender(
SimpleFormatter()
MornyFormatterConsole()
)
).minLevel(LogLevel.INFO)
)
logger minLevel LogLevels.INFO
def debug: Boolean = logger.levelSetting.minLevel.level <= LogLevel.DEBUG.level
def debug: Boolean = logger.levelSetting.minLevel.level <= LogLevels.DEBUG.level
def debug(is: Boolean): Unit =
if is then logger.minLevel(LogLevel.ALL)
else logger.minLevel(LogLevel.INFO)
if is then logger.minLevel(LogLevels.ALL)
else logger.minLevel(LogLevels.INFO)
def exceptionLog (e: Throwable): String =
val stackTrace = StringWriter()

View File

@ -27,7 +27,8 @@ class MornyCoeur (using val config: MornyConfig) {
logger info "Coeur starting..."
logger info s"args key:\n ${config.telegramBotKey}"
import cc.sukazyo.cono.morny.util.StringEnsure.deSensitive
logger info s"args key:\n ${config.telegramBotKey deSensitive 4}"
if config.telegramBotUsername ne null then
logger info s"login as:\n ${config.telegramBotUsername}"
@ -92,7 +93,7 @@ class MornyCoeur (using val config: MornyConfig) {
def saveDataAll(): Unit = {
// nothing to do
logger info "done all save action."
logger notice "done all save action."
}
private def exitCleanup (): Unit = {

View File

@ -5,11 +5,15 @@ import cc.sukazyo.cono.morny.MornyConfig.CheckFailure
import cc.sukazyo.cono.morny.util.CommonFormat
import java.time.ZoneOffset
import java.util.TimeZone
import scala.collection.mutable.ArrayBuffer
import scala.language.postfixOps
object ServerMain {
val tz: TimeZone = TimeZone getDefault
val tz_offset: ZoneOffset = ZoneOffset ofTotalSeconds (tz.getRawOffset/1000)
private val THREAD_MORNY_INIT: String = "morny-init"
def main (args: Array[String]): Unit = {
@ -135,6 +139,9 @@ object ServerMain {
|- Morny ${MornySystem.CODENAME toUpperCase}
|- <${MornySystem.getJarMD5}> [${BuildConfig.CODE_TIMESTAMP}]""".stripMargin
// due to [[MornyFormatterConsole]] will use a localized time, it will output to the log
logger info s"logging time will use time-zone ${tz.getID} ($tz_offset)"
///
/// Check Coeur arguments
/// finally start Coeur Program

View File

@ -3,8 +3,6 @@ package cc.sukazyo.cono.morny.bot.api
import com.pengrad.telegrambot.model.Update
import scala.collection.mutable
import scala.reflect.ClassTag
import scala.util.boundary
class EventEnv (
@ -24,14 +22,10 @@ class EventEnv (
def provide (i: Any): Unit =
variables += (i.getClass -> i)
def use [T] (t: Class[T]): ConsumeProvider[T] = ConsumeProvider(t)
class ConsumeProvider[T] (t: Class[T]) {
def consume (consumer: T => Unit): ConsumeResult = {
variables get t match
case Some(i) => consumer(i.asInstanceOf[T]); ConsumeResult(true)
case None => ConsumeResult(false)
}
def consume [T] (t: Class[T]) (consumer: T => Unit): ConsumeResult = {
variables get t match
case Some(i) => consumer(i.asInstanceOf[T]); ConsumeResult(true)
case None => ConsumeResult(false)
}
class ConsumeResult (success: Boolean) {

View File

@ -91,14 +91,14 @@ class MornyCommands (using coeur: MornyCoeur) {
val listing = commands_toTelegramList
automaticTGListRemove()
coeur.account exec SetMyCommands(listing:_*)
logger info
logger notice
s"""automatic updated telegram command list :
|${commandsTelegramList_toString(listing)}""".stripMargin
}
def automaticTGListRemove (): Unit = {
coeur.account exec DeleteMyCommands()
logger info "cleaned up command list"
logger notice "cleaned up command list"
}
private def commandsTelegramList_toString (list: Array[BotCommand]): String =

View File

@ -31,7 +31,7 @@ class MornyManagers (using coeur: MornyCoeur) {
event.message.chat.id,
TelegramStickers ID_EXIT
).replyToMessageId(event.message.messageId)
logger info s"Morny exited by user ${user toLogTag}"
logger attention s"Morny exited by user ${user toLogTag}"
coeur.exit(0, user)
} else {
@ -40,7 +40,7 @@ class MornyManagers (using coeur: MornyCoeur) {
event.message.chat.id,
TelegramStickers ID_403
).replyToMessageId(event.message.messageId)
logger info s"403 exit caught from user ${user toLogTag}"
logger attention s"403 exit caught from user ${user toLogTag}"
coeur.daemons.reporter.unauthenticatedAction("/exit", user)
}
@ -62,7 +62,7 @@ class MornyManagers (using coeur: MornyCoeur) {
if (coeur.trusted isTrusted user.id) {
logger info s"call save from command by ${user toLogTag}"
logger attention s"call save from command by ${user toLogTag}"
coeur.saveDataAll()
coeur.account exec SendSticker(
event.message.chat.id,
@ -75,7 +75,7 @@ class MornyManagers (using coeur: MornyCoeur) {
event.message.chat.id,
TelegramStickers ID_403
).replyToMessageId(event.message.messageId)
logger info s"403 save caught from user ${user toLogTag}"
logger attention s"403 save caught from user ${user toLogTag}"
coeur.daemons.reporter.unauthenticatedAction("/save", user)
}

View File

@ -5,13 +5,12 @@ import cc.sukazyo.cono.morny.bot.command.MornyCommands
import cc.sukazyo.cono.morny.util.tgapi.InputCommand
import cc.sukazyo.cono.morny.Log.logger
import cc.sukazyo.cono.morny.MornyCoeur
import com.pengrad.telegrambot.model.Update
class OnUniMeowTrigger (using commands: MornyCommands) (using coeur: MornyCoeur) extends EventListener {
override def onMessage (using event: EventEnv): Unit = {
event use classOf[InputCommand] consume { input =>
event.consume (classOf[InputCommand]) { input =>
logger trace s"got input command {$input} from event-context"
for ((name, command_instance) <- commands.commands_uni) {

View File

@ -30,11 +30,11 @@ class MedicationTimer (using coeur: MornyCoeur) extends Thread {
override def run (): Unit = {
if ((notify_toChat == -1) || (notify_atHour isEmpty)) {
logger info "Medication Timer disabled : related param is not complete set"
logger notice "Medication Timer disabled : related param is not complete set"
return
}
logger info "Medication Timer started."
logger notice "Medication Timer started."
while (!this.isInterrupted) {
try {
val next_time = calcNextRoutineTimestamp(System.currentTimeMillis, use_timeZone, notify_atHour)
@ -47,7 +47,7 @@ class MedicationTimer (using coeur: MornyCoeur) extends Thread {
} catch
case _: InterruptedException =>
interrupt()
logger info "MedicationTimer was interrupted, will be exit now"
logger notice "MedicationTimer was interrupted, will be exit now"
case ill: IllegalArgumentException =>
logger warn "MedicationTimer will not work due to: " + ill.getMessage
interrupt()
@ -58,7 +58,7 @@ class MedicationTimer (using coeur: MornyCoeur) extends Thread {
.stripMargin
coeur.daemons.reporter.exception(e)
}
logger info "Medication Timer stopped."
logger notice "Medication Timer stopped."
}

View File

@ -11,18 +11,18 @@ class MornyDaemons (using val coeur: MornyCoeur) {
def start (): Unit = {
logger info "ALL Morny Daemons starting..."
logger notice "ALL Morny Daemons starting..."
// TrackerDataManager.init();
medicationTimer.start()
logger info "Morny Daemons started."
logger notice "Morny Daemons started."
}
def stop (): Unit = {
logger.info("stopping All Morny Daemons...")
logger notice "stopping All Morny Daemons..."
// TrackerDataManager.DAEMON.interrupt();
medicationTimer.interrupt()
@ -31,7 +31,7 @@ class MornyDaemons (using val coeur: MornyCoeur) {
catch case e: InterruptedException =>
e.printStackTrace(System.out)
logger.info("stopped ALL Morny Daemons.")
logger notice "stopped ALL Morny Daemons."
}
}

View File

@ -0,0 +1,12 @@
package cc.sukazyo.cono.morny.internal.logging
import cc.sukazyo.messiva.log.Message
trait IMornyLogLevelImpl {
def notice (message: String): Unit
def notice (message: Message): Unit
def attention (message: String): Unit
def attention (message: Message): Unit
}

View File

@ -0,0 +1,24 @@
package cc.sukazyo.cono.morny.internal.logging
import cc.sukazyo.cono.morny.util.CommonFormat.formatDate
import cc.sukazyo.cono.morny.ServerMain
import cc.sukazyo.messiva.formatter.ILogFormatter
import cc.sukazyo.messiva.log.Log
import java.time.{ZoneId, ZoneOffset}
import java.util.TimeZone
class MornyFormatterConsole extends ILogFormatter {
override def format (log: Log): String =
val message = StringBuilder()
val dt = formatDate(log.timestamp, ServerMain.tz_offset)
val prompt_heading = s"[$dt][${log.thread.getName}]"
val prompt_newline = "'" * prompt_heading.length
val prompt_levelTag = s"${log.level.tag}::: "
message ++= prompt_heading ++= prompt_levelTag ++= log.message.message(0)
for (line <- log.message.message drop 1)
message += '\n' ++= prompt_newline ++= prompt_levelTag ++= line
message toString
}

View File

@ -0,0 +1,13 @@
package cc.sukazyo.cono.morny.internal.logging
import cc.sukazyo.messiva.log.ILogLevel
enum MornyLogLevels (
override val level: Float,
override val tag: String
) extends ILogLevel {
case NOTICE extends MornyLogLevels(0.2f, "NOTICE")
case ATTENTION extends MornyLogLevels(0.3f, "ATTION")
}

View File

@ -0,0 +1,22 @@
package cc.sukazyo.cono.morny.internal.logging
import cc.sukazyo.messiva.appender.IAppender
import cc.sukazyo.messiva.log.{Log, Message}
import cc.sukazyo.messiva.logger.Logger
class MornyLoggerBase extends Logger with IMornyLogLevelImpl {
def this (appends: IAppender*) =
this()
this.appends.addAll(java.util.List.of(appends:_*))
override def notice (message: String): Unit =
pushToAllAppender(Log(1, new Message(message), MornyLogLevels.NOTICE))
override def notice (message: Message): Unit =
pushToAllAppender(Log(1, message, MornyLogLevels.NOTICE))
override def attention (message: String): Unit =
pushToAllAppender(Log(1, new Message(message), MornyLogLevels.ATTENTION))
override def attention (message: Message): Unit =
pushToAllAppender(Log(1, message, MornyLogLevels.ATTENTION))
}

View File

@ -12,6 +12,9 @@ object StringEnsure {
} else str
}
def deSensitive (keepStart: Int = 2, keepEnd: Int = 4, sensitive_cover: Char = '*'): String =
(str take keepStart) + (sensitive_cover.toString*(str.length-keepStart-keepEnd)) + (str takeRight keepEnd)
}
}

1
src/test/scala/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
live

View File

@ -1,14 +0,0 @@
package live
import cc.sukazyo.cono.morny.bot.api.EventEnv
import cc.sukazyo.cono.morny.test.utils.BiliToolTest
@main def LiveMain (args: String*): Unit = {
val env: EventEnv = EventEnv(null)
env provide "abcdefg"
env use classOf[String] consume { (str: String) => println(str) } onfail { println("no str found in the env") }
}