-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Logging zh TW
ASF允許您自訂執行期間使用的紀錄日誌模組。 您可以將叫做NLog.config
的特定檔案存放至應用程式的資料夾中來達成自訂。 您可以在NLog Wiki中閱讀完整的文件,但除此之外,您也可以在這裡找到一些有用的範例。
預設情形下,ASF會記錄於ColoredConsole
(標準輸出)及File
中。 File
紀錄包含在程式資料夾中的log.txt
檔案及用於歸檔的logs
資料夾中。
使用自訂NLog設定會自動停用預設的ASF設定,您的設定會完全覆寫預設的ASF紀錄,這代表例如您想要保留我們的ColoredConsole
目標,就必須自行定義。 這使您不只能夠新增額外的紀錄目標,還可以停用或修改預設的目標。
若您想要使用不受任何修改的預設ASF紀錄,就什麼也不需要做⸺您也不需要在自訂的NLog.config
中定義它。 若您不想要修改預設ASF紀錄,就不要使用自訂的NLog.config
。 不過做為參考,硬編碼的ASF預設紀錄等同於:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" layout="${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}" />
<target xsi:type="File" name="File" archiveFileName="${currentdir}/logs/log.{#}.txt" archiveNumbering="Rolling" archiveOldFileOnStartup="true" cleanupFileName="false" concurrentWrites="false" deleteOldFileOnStartup="true" fileName="${currentdir}/log.txt" layout="${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}" maxArchiveFiles="10" />
<!-- 在ASF的IPC介面啟動時,下列將變為活動狀態 -->
<target type="History" name="History" layout="${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}" maxCount="20" />
</targets>
<rules>
<!-- 下列項指定了ASP.NET(IPC)紀錄,我們宣告它們,因此我們最頂層的Debug catch-all在預設情形下不包含ASP.NET紀錄 -->
<logger name="Microsoft*" finalMinLevel="Warn" writeTo="ColoredConsole" />
<logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" writeTo="ColoredConsole" />
<logger name="System*" finalMinLevel="Warn" writeTo="ColoredConsole" />
<logger name="*" minlevel="Debug" writeTo="ColoredConsole" />
<!-- 下列項指定了ASP.NET(IPC)紀錄,我們宣告它們,因此我們最頂層的Debug catch-all在預設情形下不包含ASP.NET紀錄 -->
<logger name="Microsoft*" finalMinLevel="Warn" writeTo="File" />
<logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" writeTo="File" />
<logger name="System*" finalMinLevel="Warn" writeTo="File" />
<logger name="*" minlevel="Debug" writeTo="File" />
<!-- 在ASF的IPC介面啟用時,下列將變為活動狀態 -->
<!-- 下列項指定了ASP.NET(IPC)紀錄,我們宣告它們,因此我們最頂層的Debug catch-all在預設情形下不包含ASP.NET紀錄 -->
<logger name="Microsoft*" finalMinLevel="Warn" writeTo="History" />
<logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" writeTo="History" />
<logger name="System*" finalMinLevel="Warn" writeTo="History" />
<logger name="*" minlevel="Debug" writeTo="History" />
</rules>
</nlog>
ASF含有一些不錯的程式碼技巧,可以增強與NLog的整合,使您可以更輕鬆地抓取特定訊息。
NLog特定的${logger}
變數將始終用來識別訊息來源⸺可以是您的Bot之一的BotName
;若訊息直接來自ASF程序,也可以是ASF
。 透過這種方式,您可以依據記錄器的名稱輕鬆抓取特定Bot或(只捕獲)ASF程序的訊息,而不是全部。
ASF會嘗試依據NLog提供的記錄級別適當地標示訊息,使您可以只抓取來自特定記錄級別的特定訊息,而不是全部。 當然,特定訊息的記錄級別無法自訂,因為這是ASF硬編碼所決定的訊息嚴重程度,但您仍絕對可以使ASF更加/更少的「沉默」,來符合您的需求。
ASF也會記錄額外資訊,例如在Trace
的記錄級別中就包含使用者使用者/聊天訊息。 預設的ASF紀錄只記錄了Debug
級別及以上的訊息,它隱藏了額外訊息,因為大多數使用者並不需要它們,況且這些雜項輸出可能會掩蓋掉重要訊息。 但是您可以透過重新啟用Trace
記錄級別來使用該訊息,特別是您只需要記錄某個特定Bot及您感興趣的特定事件的時候。
一般來說,ASF試圖讓您盡可能地簡單且方便,只記錄您想要的訊息,而不是強迫您透過grep
等第三方工具來手動過濾它。 只需依照下列說明正確地設定NLog,您就應該能夠使用自訂目標(例如整個資料庫)指定的非常複雜的記錄規則。
關於版本控制⸺ASF嘗試始終在發布時提供當時NuGet上最新版的NLog。 您應該能夠使用所有您能在NLog Wiki上找到的ASF功能⸺只需要確保您也使用最新版的ASF。
作為ASF整合的一部份,ASF也支援包含其他ASF NLog紀錄的目標,這將在下列說明。
讓我們從簡單的地方開始。 We will use ColoredConsole target only. Our initial NLog.config
will look like this:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="ColoredConsole" />
</rules>
</nlog>
The explanation of above config is rather simple - we define one logging target, which is ColoredConsole
, then we redirect all loggers (*
) of level Debug
and higher to ColoredConsole
target we defined earlier. That's it.
If you start ASF with above NLog.config
now, only ColoredConsole
target will be active, and ASF won't write to File
, regardless of hardcoded ASF NLog configuration.
Now let's say that we don't like default format of ${longdate}|${level:uppercase=true}|${logger}|${message}
and we want to log message only. We can do so by modifying Layout of our target.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" layout="${message}" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="ColoredConsole" />
</rules>
</nlog>
If you launch ASF now, you'll notice that date, level and logger name disappeared - leaving you only with ASF messages in format of Function() Message
.
We can also modify the config to log to more than one target. Let's log to ColoredConsole
and File at the same time.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" />
<target xsi:type="File" name="File" fileName="${currentdir}/NLog.txt" deleteOldFileOnStartup="true" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="ColoredConsole" />
<logger name="*" minlevel="Debug" writeTo="File" />
</rules>
</nlog>
And done, we'll now log everything to ColoredConsole
and File
. Did you notice that you can also specify custom fileName
and extra options?
Finally, ASF uses various log levels, to make it easier for you to understand what is going on. We can use that information for modifying severity logging. Let's say that we want to log everything (Trace
) to File
, but only Warning
and above log level to the ColoredConsole
. We can achieve that by modifying our rules
:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" />
<target xsi:type="File" name="File" fileName="${currentdir}/NLog.txt" deleteOldFileOnStartup="true" />
</targets>
<rules>
<logger name="*" minlevel="Warn" writeTo="ColoredConsole" />
<logger name="*" minlevel="Trace" writeTo="File" />
</rules>
</nlog>
That's it, now our ColoredConsole
will show only warnings and above, while still logging everything to File
. You can further tweak it to log e.g. only Info
and below, and so on.
Lastly, let's do something a bit more advanced and log all messages to file, but only from bot named LogBot
.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" />
<target xsi:type="File" name="LogBotFile" fileName="${currentdir}/LogBot.txt" deleteOldFileOnStartup="true" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="ColoredConsole" />
<logger name="LogBot" minlevel="Trace" writeTo="LogBotFile" />
</rules>
</nlog>
You can see how we used ASF integration above and easily distinguished source of the message based on ${logger}
property.
The examples above are rather simple and made to show you how easy it is to define your own logging rules that can be used with ASF. You can use NLog for various different things, including complex targets (such as keeping logs in Database
), logs rotation (such as removing old File
logs), using custom Layout
s, declaring your own <when>
logging filters and much more. I encourage you to read through entire NLog documentation to learn about every option that is available to you, allowing you to fine-tune ASF logging module in the way you want. It's a really powerful tool and customizing ASF logging was never easier.
ASF will temporarily disable all rules that include ColoredConsole
or Console
targets when expecting user input. Therefore, if you want to keep logging for other targets even when ASF expects user input, you should define those targets with their own rules, as shown in examples above, instead of putting many targets in writeTo
of the same rule (unless this is your wanted behaviour). Temporary disable of console targets is done in order to keep console clean when waiting for user input.
ASF includes extended support for chat logging by not only recording all received/sent messages on Trace
logging level, but also exposing extra info related to them in event properties. This is because we need to handle chat messages as commands anyway, so it doesn't cost us anything to log those events in order to make it possible for you to add extra logic (such as making ASF your personal Steam chatting archive).
名稱 | 描述 |
---|---|
Echo |
bool 型別。 This is set to true when message is being sent from us to the recipient, and false otherwise. |
Message |
string 型別。 This is the actual sent/received message. |
ChatGroupID |
ulong 型別。 This is the ID of the group chat for sent/received messages. Will be 0 when no group chat is used for transmitting this message. |
ChatID |
ulong 型別。 This is the ID of the ChatGroupID channel for sent/received messages. Will be 0 when no group chat is used for transmitting this message. |
SteamID |
ulong 型別。 This is the ID of the Steam user for sent/received messages. Can be 0 when no particular user is involved in the message transmission (e.g. when it's us sending a message to a group chat). |
This example is based on our ColoredConsole
basic example above. Before trying to understand it, I strongly recommend to take a look above in order to learn about basics of NLog logging firstly.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="ColoredConsole" name="ColoredConsole" />
<target xsi:type="File" name="ChatLogFile" fileName="${currentdir}/${event-properties:item=ChatGroupID}-${event-properties:item=ChatID}${when:when='${event-properties:item=ChatGroupID}' == 0:inner=-${event-properties:item=SteamID}}.txt" layout="${date:format=yyyy-MM-dd HH\:mm\:ss} ${event-properties:item=Message} ${when:when='${event-properties:item=Echo}' == true:inner=->:else=<-} ${event-properties:item=SteamID}" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="ColoredConsole" />
<logger name="MainAccount" level="Trace" writeTo="ChatLogFile">
<filters defaultAction="Log">
<when condition="not starts-with('${message}','OnIncoming') and not starts-with('${message}','SendMessage')" action="Ignore" />
</filters>
</logger>
</rules>
</nlog>
We've started from our basic ColoredConsole
example and extended it further. First and foremost, we've prepared a permanent chat log file per each group channel and Steam user - this is possible thanks to extra properties that ASF exposes to us in a fancy way. We've also decided to go with a custom layout that writes only current date, the message, sent/received info and Steam user itself. Lastly, we've enabled our chat logging rule only for Trace
level, only for our MainAccount
bot and only for functions related to chat logging (OnIncoming*
which is used for receiving messages and echos, and SendMessage*
for ASF messages sending).
The example above will generate 0-0-76561198069026042.txt
file when talking with ArchiBot:
2018-07-26 01:38:38 how are you doing? -> 76561198069026042
2018-07-26 01:38:38 I'm doing great, how about you? <- 76561198069026042
Of course this is just a working example with a few nice layout tricks showed in practical manner. You can further expand this idea to your own needs, such as extra filtering, custom order, personal layout, recording only received messages and so on.
In addition to standard NLog logging targets (such as ColoredConsole
and File
explained above), you can also use custom ASF logging targets.
For maximum completeness, definition of ASF targets will follow NLog documentation convention.
As you can guess, this target uses Steam chat messages for logging ASF messages. You can configure it to use either a group chat, or private chat. In addition to specifying a Steam target for your messages, you can also specify botName
of the bot that is supposed to send those.
Supported in all environments used by ASF.
<targets>
<target type="Steam"
name="String"
layout="Layout"
chatGroupID="Ulong"
steamID="Ulong"
botName="Layout" />
</targets>
Read more about using the Configuration File.
name - Name of the target.
layout - Text to be rendered. Layout Required. Default: ${level:uppercase=true}|${logger}|${message}
chatGroupID - ID of the group chat declared as 64-bit long unsigned integer. 非必要。 Defaults to 0
which will disable group chat functionality and use private chat instead. When enabled (set to non-zero value), steamID
property below acts as chatID
and specifies ID of the channel in this chatGroupID
that the bot should send messages to.
steamID - SteamID declared as 64-bit long unsigned integer of target Steam user (like SteamOwnerID
), or target chatID
(when chatGroupID
is set). Required. Defaults to 0
which disables logging target entirely.
botName - Name of the bot (as it's recognized by ASF, case-sensitive) that will be sending messages to steamID
declared above. 非必要。 Defaults to null
which will automatically select any currently connected bot. It's recommended to set this value appropriately, as SteamTarget
does not take into account many Steam limitations, such as the fact that you must have steamID
of the target on your friendlist. This variable is defined as layout type, therefore you can use special syntax in it, such as ${logger}
in order to use the bot that generated the message.
In order to write all messages of Debug
level and above, from bot named MyBot
to steamID of 76561198006963719
, you should use NLog.config
similar to below:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="https://nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<targets>
<target type="Steam" name="Steam" steamID="76561198006963719" botName="MyBot" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="Steam" />
</rules>
</nlog>
Notice: Our SteamTarget
is custom target, so you should make sure that you're declaring it as type="Steam"
, NOT xsi:type="Steam"
, as xsi is reserved for official targets supported by NLog.
When you launch ASF with NLog.config
similar to above, MyBot
will start messaging 76561198006963719
Steam user with all usual ASF log messages. Keep in mind that MyBot
must be connected in order to send messages, so all initial ASF messages that happened before our bot could connect to Steam network, won't be forwarded.
Of course, SteamTarget
has all typical functions that you could expect from generic TargetWithLayout
, so you can use it in conjunction with e.g. custom layouts, names or advanced logging rules. The example above is only the most basic one.
This target is used internally by ASF for providing fixed-size logging history in /Api/NLog
endpoint of ASF API that can be afterwards consumed by ASF-ui and other tools. In general you should define this target only if you're already using custom NLog config for other customizations and you also want the log to be exposed in ASF API, e.g. for ASF-ui. It can also be declared when you'd want to modify default layout or maxCount
of saved messages.
Supported in all environments used by ASF.
<targets>
<target type="History"
name="String"
layout="Layout"
maxCount="Byte" />
</targets>
Read more about using the Configuration File.
name - Name of the target.
layout - Text to be rendered. Layout Required. Default: ${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}
maxCount - Maximum amount of stored logs for on-demand history. 非必要。 Defaults to 20
which is a good balance for providing initial history, while still keeping in mind memory usage that comes out of storage requirements. Must be greater than 0
.
Be careful when you decide to combine Debug
logging level or below in your SteamTarget
with steamID
that is taking part in the ASF process. This can lead to potential StackOverflowException
because you'll create an infinite loop of ASF receiving given message, then logging it through Steam, resulting in another message that needs to be logged. Currently the only possibility for it to happen is to log Trace
level (where ASF records its own chat messages), or Debug
level while also running ASF in Debug
mode (where ASF records all Steam packets).
In short, if your steamID
is taking part in the same ASF process, then the minlevel
logging level of your SteamTarget
should be Info
(or Debug
if you're also not running ASF in Debug
mode) and above. Alternatively you can define your own <when>
logging filters in order to avoid infinite logging loop, if modifying level is not appropriate for your case. This caveat also applies to group chats.