diff --git a/PackageScript b/PackageScript index 4aa852e..cba48ed 100644 --- a/PackageScript +++ b/PackageScript @@ -11,8 +11,8 @@ folder_list = [ 'addons/sourcemod/scripting/include', 'addons/sourcemod/scripting/include/log4sp', 'addons/sourcemod/scripting/include/log4sp/sinks', - 'addons/sourcemod/scripting/include/log4sp_empty', - 'addons/sourcemod/scripting/include/log4sp_empty/sinks', + 'addons/sourcemod/scripting/include/log4sp_no_ext', + 'addons/sourcemod/scripting/include/log4sp_no_ext/sinks', #'addons/sourcemod/gamedata', #'addons/sourcemod/configs', ] @@ -52,13 +52,13 @@ CopyFiles('sourcemod/scripting/include/log4sp/sinks', 'addons/sourcemod/scriptin 'client_console_sink.inc' ] ) -CopyFiles('sourcemod/scripting/include/log4sp_empty', 'addons/sourcemod/scripting/include/log4sp_empty', +CopyFiles('sourcemod/scripting/include/log4sp_no_ext', 'addons/sourcemod/scripting/include/log4sp_no_ext', [ 'common.inc', 'logger.inc' ] ) -CopyFiles('sourcemod/scripting/include/log4sp_empty/sinks', 'addons/sourcemod/scripting/include/log4sp_empty/sinks', +CopyFiles('sourcemod/scripting/include/log4sp_no_ext/sinks', 'addons/sourcemod/scripting/include/log4sp_no_ext/sinks', [ 'sink.inc', 'server_console_sink.inc', diff --git a/sourcemod/scripting/include/log4sp/common.inc b/sourcemod/scripting/include/log4sp/common.inc index 9f84b5e..4058199 100644 --- a/sourcemod/scripting/include/log4sp/common.inc +++ b/sourcemod/scripting/include/log4sp/common.inc @@ -98,6 +98,6 @@ native void LogLevelToShortName(LogLevel lvl, char[] buffer, int maxlen); * Convert a logging level name to log level enum. * * @param name Log level name. - * @return Logging level enum or LogLevel_Off when the log level name does not exist. + * @return Logging level enum or LogLevel_Off when the logging level name does not exist. */ native LogLevel NameToLogLevel(const char[] name); diff --git a/sourcemod/scripting/include/log4sp/logger.inc b/sourcemod/scripting/include/log4sp/logger.inc index 900ec82..3ff3ecf 100644 --- a/sourcemod/scripting/include/log4sp/logger.inc +++ b/sourcemod/scripting/include/log4sp/logger.inc @@ -10,32 +10,33 @@ #include -typeset Log4spErrorCallback +typeset LoggerErrorHandler { - function void (const char[] msg); + function void (Logger logger, const char[] msg); }; methodmap Logger < Handle { /** - * Creating logger handle manually. + * Creating a logger handle manually. * * @param name The name of the new logger. * @param sinks The sinks array to be added to the new logger. * @param numSinks The number of slots in the sinks array. - * @param async If true, the sink of the new logger will be multi threaded. - * @param policy Message queue overflow policy. (Only used when async=true) + * @param async If true, Log operations will be pushed to background threads for processing, + * which can avoid blocking the main thread. + * @param policy Message queue overflow policy. (Only used when async = true) * @return Logger handle. * @error Logger name already exits, or the sinks has an invalid handle. */ public native Logger(const char[] name, Sink[] sinks, int numSinks, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block); /** - * Get a logger handle by logger name. + * Gets a logger handle by logger name. * * @param name The name of the logger. - * @return Return an existing logger handle or INVALID_HANDLE if a logger with such name doesn't exist. + * @return Logger handle or INVALID_HANDLE if the logger name does not exist. */ public static native Logger Get(const char[] name); @@ -43,8 +44,9 @@ methodmap Logger < Handle * Create a logger handle that outputs to the server console. * * @param name The name of the new logger. - * @param async If true, the sink of the new logger will be multi threaded. - * @param policy Message queue overflow policy. (Only used when async=true) + * @param async If true, Log operations will be pushed to background threads for processing, + * which can avoid blocking the main thread. + * @param policy Message queue overflow policy. (Only used when async = true) * @return Logger handle. * @error Logger name already exits. */ @@ -56,8 +58,9 @@ methodmap Logger < Handle * @param name The name of the new logger. * @param file The file path where the log messages will be written. * @param truncate If true, the created file will be truncated. - * @param async If true, the sink of the new logger will be multi threaded. - * @param policy Message queue overflow policy. (Only used when async=true) + * @param async If true, Log operations will be pushed to background threads for processing, + * which can avoid blocking the main thread. + * @param policy Message queue overflow policy. (Only used when async = true) * @return Logger handle. * @error Logger name already exits. */ @@ -81,8 +84,9 @@ methodmap Logger < Handle * @param maxFileSize The maximum size of the log file in bytes before it gets rotated. * @param maxFiles The maximum number of rotated log files to keep. * @param rotateOnOpen If true, the log file will be rotated when opened. - * @param async If true, the sink of the new logger will be multi threaded. - * @param policy Message queue overflow policy. (Only used when async=true) + * @param async If true, Log operations will be pushed to background threads for processing, + * which can avoid blocking the main thread. + * @param policy Message queue overflow policy. (Only used when async = true) * @return Logger handle. * @error Logger name already exits, or maxFileSize == 0, or maxFiles > 200000. */ @@ -103,8 +107,9 @@ methodmap Logger < Handle * @param minute The minute of the hour when the log file should be rotated. (0-59) * @param truncate If true, the created file will be truncated. * @param maxFiles If max_files > 0, retain only the last max_files and delete previous. - * @param async If true, the sink of the new logger will be multi threaded. - * @param policy Message queue overflow policy. (Only used when async=true) + * @param async If true, Log operations will be pushed to background threads for processing, + * which can avoid blocking the main thread. + * @param policy Message queue overflow policy. (Only used when async = true) * @return Logger handle. * @error Logger name already exits, or invalid rotation time. */ @@ -118,7 +123,7 @@ methodmap Logger < Handle AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block); /** - * Get the logger name. + * Gets the logger name. * * @param buffer Buffer to store logger name. * @param maxlen Maximum length of the buffer. @@ -126,21 +131,21 @@ methodmap Logger < Handle public native void GetName(char[] buffer, int maxlen); /** - * Get the logger log level. + * Gets the logger log level. * * @return The logger log level. */ public native LogLevel GetLevel(); /** - * Set the logger log level. + * Sets the logger log level. * - * @param lvl Logging level enum. + * @param lvl Log level enum. */ public native void SetLevel(LogLevel lvl); /** - * Set formatting for the sinks in this logger. + * Sets formatting for the sinks in the logger. * * @note each sink will get a new instance of a formatter object, replacing the old one. * @note pattern flags: https://github.com/gabime/spdlog/wiki/3.-Custom-formatting#pattern-flags @@ -151,52 +156,56 @@ methodmap Logger < Handle public native void SetPattern(const char[] pattern, PatternTimeType type = PatternTimeType_Local); /** - * Gets whether logging at the given log level is enabled. + * Gets whether logging is enabled for the given log level. * - * @param lvl Logging level enum. - * @return True if logging is enabled for the given level. + * @param lvl Log level enum. + * @return True if logging is enabled for the given log level. */ public native bool ShouldLog(LogLevel lvl); /** * Logs a message. * - * @param lvl Logging level enum. - * @param msg Logging message. + * @param lvl Log level enum. + * @param msg Log message. */ public native void Log(LogLevel lvl, const char[] msg); public native void LogEx(LogLevel lvl, const char[] fmt, any ...); + public native void LogAmxTpl(LogLevel lvl, const char[] fmt, any ...); /** * Logs a message with the sourcepawn source code location. * - * @param lvl Logging level enum. - * @param msg Logging message. + * @param lvl Log level enum. + * @param msg Log message. */ public native void LogSrc(LogLevel lvl, const char[] msg); public native void LogSrcEx(LogLevel lvl, const char[] fmt, any ...); + public native void LogSrcAmxTpl(LogLevel lvl, const char[] fmt, any ...); /** - * Logs a message with the source code location. + * Logs a message with the given source code location. * * @param file The file name of the source code location. * @param line The line number of the source code location. * @param func The function name of the source code location. - * @param lvl Logging level enum. - * @param msg Logging message. + * @param lvl Log level enum. + * @param msg Log message. */ public native void LogLoc(const char[] file, int line, const char[] func, LogLevel lvl, const char[] msg); public native void LogLocEx(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...); + public native void LogLocAmxTpl(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...); /** * Logs a stack trace from the current function call. * Code execution continues after the call. * - * @param lvl Logging level enum. - * @param msg Logging message. + * @param lvl Log level enum. + * @param msg Log message. */ public native void LogStackTrace(LogLevel lvl, const char[] msg); public native void LogStackTraceEx(LogLevel lvl, const char[] fmt, any ...); + public native void LogStackTraceAmxTpl(LogLevel lvl, const char[] fmt, any ...); /** * Aborts the current callback and throws an error. @@ -204,30 +213,37 @@ methodmap Logger < Handle * * @note The only difference from ThorwError() is that it also log the message into the logger's sinks. * - * @param lvl Logging level enum. - * @param msg Logging message. + * @param lvl Log level enum. + * @param msg Log message. * @error Always! */ public native void ThrowError(LogLevel lvl, const char[] msg); public native void ThrowErrorEx(LogLevel lvl, const char[] fmt, any ...); + public native void ThrowErrorAmxTpl(LogLevel lvl, const char[] fmt, any ...); public native void Trace(const char[] msg); public native void TraceEx(const char[] fmt, any ...); + public native void TraceAmxTpl(const char[] fmt, any ...); public native void Debug(const char[] msg); public native void DebugEx(const char[] fmt, any ...); + public native void DebugAmxTpl(const char[] fmt, any ...); public native void Info(const char[] msg); public native void InfoEx(const char[] fmt, any ...); + public native void InfoAmxTpl(const char[] fmt, any ...); public native void Warn(const char[] msg); public native void WarnEx(const char[] fmt, any ...); + public native void WarnAmxTpl(const char[] fmt, any ...); public native void Error(const char[] msg); public native void ErrorEx(const char[] fmt, any ...); + public native void ErrorAmxTpl(const char[] fmt, any ...); public native void Fatal(const char[] msg); public native void FatalEx(const char[] fmt, any ...); + public native void FatalAmxTpl(const char[] fmt, any ...); /** * Manual flush logger contents. @@ -235,25 +251,23 @@ methodmap Logger < Handle public native void Flush(); /** - * Get the minimum log level that will trigger automatic flush. + * Gets the minimum log level that will trigger automatic flush. * * @return the minimum log level that will trigger automatic flush. */ public native LogLevel GetFlushLevel(); /** - * Set the minimum log level that will trigger automatic flush. + * Sets the minimum log level that will trigger automatic flush. * - * @note If lvl out of bounds, native will be modified to the nearest boundary. - * - * @param lvl Logging level enum. + * @param lvl Log level enum. */ public native void FlushOn(LogLevel lvl); /** * Gets whether backtrace logging is enabled. * - * @return Return true if backtrace logging is enabled. + * @return True if backtrace logging is enabled. */ public native bool ShouldBacktrace(); @@ -277,28 +291,24 @@ methodmap Logger < Handle /** * Add a new sink to sinks. * - * @param sink Handle of sink. + * @param sink Sink handle. * @error Invalid sink handle. */ public native void AddSink(Sink sink); /** - * Drop the reference to the given sink + * Remove a sink from the sinks. * - * @param sink Handle of Sink. - * @return True on success, false if the sink was not found. + * @param sink Sink handle. * @error Invalid sink handle. */ - public native bool DropSink(Sink sink); + public native void DropSink(Sink sink); /** - * Sets the callback when logging errors occur. - * - * @note This machine is not thread safe. - * Recommend using this native only during initialization. + * Sets the handler function for logging errors. * - * @param callback A callback called when an error occurs. - * @error Invalid error callback. + * @param handler A handler function that is called when an error occurs. + * @error Invalid error handler function. */ - public native void SetErrorHandler(Log4spErrorCallback callback); + public native void SetErrorHandler(LoggerErrorHandler handler); } diff --git a/sourcemod/scripting/include/log4sp/sinks/base_file_sink.inc b/sourcemod/scripting/include/log4sp/sinks/base_file_sink.inc index 22c62a7..7cac3ad 100644 --- a/sourcemod/scripting/include/log4sp/sinks/base_file_sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/base_file_sink.inc @@ -14,12 +14,12 @@ methodmap BaseFileSink < Sink /** * Trivial file sink with single file as target. * - * @param file The file path where the log messages will be written. - * @param truncate If true, the created file will be truncated. - * @param async If true, the sink will be multi threaded. - * @return Handle for a base file sink. + * @param file The file path where the log messages will be written. + * @param truncate If true, the created file will be truncated. + * @param multiThread If true, the created sink will be multi threaded and thread safe. + * @return BaseFileSink handle. */ - public native BaseFileSink(const char[] file, bool truncate = false, bool aysnc = false); + public native BaseFileSink(const char[] file, bool truncate = false, bool multiThread = false); /** * Get the current filename being used by the file sink. diff --git a/sourcemod/scripting/include/log4sp/sinks/client_chat_sink.inc b/sourcemod/scripting/include/log4sp/sinks/client_chat_sink.inc index 8ed8187..fc3fbb1 100644 --- a/sourcemod/scripting/include/log4sp/sinks/client_chat_sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/client_chat_sink.inc @@ -8,44 +8,21 @@ #include -/** - * The filter is called at client_chat_sink::sink_it_. - * filter return Plugin_Continue to allow sink to the client chat, others skip sink to the client chat. - * - * extension only call filter when the client in game, so you don't need this code: "if (IsClientInGame(client)) ". - * - * By default (no filter is set), the sink will sink to all in game clients. - - * Param msg is a message that has been formatted but not yet formatted by a pattern. - * - * For example, only sink to alive client - * Action FilterAlivePlayer(int client) { - * return IsPlayerAlive(client) ? Plugin_Continue : Plugin_Handled; - * } - */ -typeset ClientChatSinkFilter -{ - function Action (int client); - function Action (int client, const char[] name, LogLevel lvl); - function Action (int client, const char[] name, LogLevel lvl, const char[] msg); -}; - - methodmap ClientChatSink < Sink { /** * This sink is output to all client chat. * - * @param async If true, the sink will be multi threaded. - * @return Handle for a client chat sink. + * @param multiThread If true, the created sink will be multi threaded and thread safe. + * @return ClientChatSink handle. */ - public native ClientChatSink(bool async = false); + public native ClientChatSink(bool multiThread = false); /** * Set the clint chat sink filter. * * @error Invalid client chat sink filter. */ - public native void SetFilter(ClientChatSinkFilter filter); + public native void SetFilter(SinkClientFilter filter); } diff --git a/sourcemod/scripting/include/log4sp/sinks/client_console_sink.inc b/sourcemod/scripting/include/log4sp/sinks/client_console_sink.inc index 4a6ca4a..d4ccf9c 100644 --- a/sourcemod/scripting/include/log4sp/sinks/client_console_sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/client_console_sink.inc @@ -8,46 +8,21 @@ #include -/** - * The filter is called at client_console_sink::sink_it_. - * filter return Plugin_Continue to allow sink to the client console, - * others skip sink to the client console. - * - * extension only call filter when the client in game, - * so you don't need this code: "if (IsClientInGame(client)) ". - * - * By default (no filter is set), the sink will sink to all in game clients. - * - * Param msg is a message that has been formatted but not yet formatted by a pattern. - * - * For example, only sink to alive client - * Action FilterAlivePlayer(int client) { - * return IsPlayerAlive(client) ? Plugin_Continue : Plugin_Handled; - * } - */ -typeset ClientConsoleSinkFilter -{ - function Action (int client); - function Action (int client, const char[] name, LogLevel lvl); - function Action (int client, const char[] name, LogLevel lvl, const char[] msg); -}; - - methodmap ClientConsoleSink < Sink { /** * This sink is output to all client console. * - * @param async If true, the sink will be multi threaded. - * @return Handle for a client console sink. + * @param multiThread If true, the created sink will be multi threaded and thread safe. + * @return ClientConsoleSink handle. */ - public native ClientConsoleSink(bool async = false); + public native ClientConsoleSink(bool multiThread = false); /** * Set the clint console sink filter. * - * @error Invalid client console sink filter. + * @error Invalid client console sink filter. */ - public native void SetFilter(ClientConsoleSinkFilter filter); + public native void SetFilter(SinkClientFilter filter); } diff --git a/sourcemod/scripting/include/log4sp/sinks/daily_file_sink.inc b/sourcemod/scripting/include/log4sp/sinks/daily_file_sink.inc index 61692ad..62bb575 100644 --- a/sourcemod/scripting/include/log4sp/sinks/daily_file_sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/daily_file_sink.inc @@ -9,10 +9,8 @@ #include -/* +/** * Rotating file sink based on date. - * If truncate != false , the created file will be truncated. - * If max_files > 0, retain only the last max_files and delete previous. */ methodmap DailyFileSink < Sink { @@ -24,8 +22,8 @@ methodmap DailyFileSink < Sink * @param rotationMinute The minute of the hour when the log file should be rotated. (0-59) * @param truncate If true, the created file will be truncated. * @param maxFiles If max_files > 0, retain only the last max_files and delete previous. - * @param async If true, the sink will be multi threaded. - * @return Handle for a daily file sink. + * @param multiThread If true, the created sink will be multi threaded and thread safe. + * @return DailyFileSink handle. * @error Invalid rotation time in ctor. */ public native DailyFileSink(const char[] file, @@ -33,7 +31,7 @@ methodmap DailyFileSink < Sink int rotationMinute = 0, bool truncate = false, int maxFiles = 0, - bool async = false); + bool multiThread = false); /** * Get the current filename being used by the file sink. diff --git a/sourcemod/scripting/include/log4sp/sinks/rotating_file_sink.inc b/sourcemod/scripting/include/log4sp/sinks/rotating_file_sink.inc index 82fd782..c88ef6c 100644 --- a/sourcemod/scripting/include/log4sp/sinks/rotating_file_sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/rotating_file_sink.inc @@ -9,29 +9,31 @@ #include +/** + * Rotate files: + * log.txt -> log.1.txt + * log.1.txt -> log.2.txt + * log.2.txt -> log.3.txt + * log.3.txt -> delete + */ methodmap RotatingFileSink < Sink { /** * Rotating file sink based on size. - * Rotate files: - * log.txt -> log.1.txt - * log.1.txt -> log.2.txt - * log.2.txt -> log.3.txt - * log.3.txt -> delete * * @param file The file path where the log messages will be written. * @param maxFileSize The maximum size of the log file in bytes before it gets rotated. * @param maxFiles The maximum number of rotated log files to keep. * @param rotateOnOpen If true, the log file will be rotated when opened. - * @param async If true, the sink will be multi threaded. - * @return Handle for a rotating file sink. + * @param multiThread If true, the created sink will be multi threaded and thread safe. + * @return RotatingFileSink handle. * @error Param maxFileSize <= 0, Param maxFiles > 200000. */ public native RotatingFileSink(const char[] file, const int maxFileSize, const int maxFiles, bool rotateOnOpen = false, - bool async = false); + bool multiThread = false); /** * Get the current filename being used by the file sink. diff --git a/sourcemod/scripting/include/log4sp/sinks/server_console_sink.inc b/sourcemod/scripting/include/log4sp/sinks/server_console_sink.inc index 66d6f54..982ab4d 100644 --- a/sourcemod/scripting/include/log4sp/sinks/server_console_sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/server_console_sink.inc @@ -14,7 +14,8 @@ methodmap ServerConsoleSink < Sink /** * This sink is output to the server console. * - * @return Handle for a server console sink. + * @param multiThread If true, the created sink will be multi threaded and thread safe. + * @return ServerConsoleSink handle. */ - public native ServerConsoleSink(); + public native ServerConsoleSink(bool multiThread = false); } diff --git a/sourcemod/scripting/include/log4sp/sinks/sink.inc b/sourcemod/scripting/include/log4sp/sinks/sink.inc index 0121c5d..a53f4d4 100644 --- a/sourcemod/scripting/include/log4sp/sinks/sink.inc +++ b/sourcemod/scripting/include/log4sp/sinks/sink.inc @@ -15,16 +15,16 @@ methodmap Sink < Handle { /** - * Get the current logging level. + * Gets the sink log level. * - * @return The current logging level. + * @return The sink log level. */ public native LogLevel GetLevel(); /** - * Set the logging level. + * Sets the sink log level. * - * @param lvl Logging level enum. + * @param lvl Log level enum. */ public native void SetLevel(LogLevel lvl); @@ -39,45 +39,46 @@ methodmap Sink < Handle public native void SetPattern(const char[] pattern); /** - * Gets whether logging at the given log level is enabled. + * Gets whether logging is enabled for the given log level. * - * @param lvl Logging level enum. - * @return True if logging is enabled for the given level. + * @param lvl Log level enum. + * @return True if logging is enabled for the given log level. */ public native bool ShouldLog(LogLevel lvl); /** - * Logging a Message. + * Logs a message. * - * @param name The name of the logger. - * @param lvl Logging level enum. - * @param msg Logging message. + * @param name The name of a logger. + * @param lvl Log level enum. + * @param msg Log message. */ public native void Log(const char[] name, LogLevel lvl, const char[] msg); - /** - * Logging a message with the sourcepawn source code location. - * - * @param name The name of the logger. - * @param lvl Logging level enum. - * @param msg Logging message. - */ - public native void LogSrc(const char[] name, LogLevel lvl, const char[] msg); - - /** - * Logging a message with the source code location. - * - * @param file Source code location File name. - * @param line Source code location File line number. - * @param func Source code location Function name. - * @param name The name of the logger. - * @param lvl Logging level enum. - * @param msg Logging message. - */ - public native void LogLoc(const char[] file, int line, const char[] func, const char[] name, LogLevel lvl, const char[] msg); - /** * Manual flush logger contents. */ public native void Flush(); } + + +/** + * The filter is called at sink::sink_it_. + * filter return Plugin_Continue to allow sink it, others skip sink it to this client. + * + * extension only call filter when the client in game, so you don't need this code: "if (IsClientInGame(client)) ". + * By default (no filter is set), the sink will sink to all in game clients. + * + * Param msg is a message that has been formatted but not yet formatted by a pattern. + * + * For example, only sink to alive client + * Action FilterAlivePlayer(int client) { + * return IsPlayerAlive(client) ? Plugin_Continue : Plugin_Handled; + * } + */ +typeset SinkClientFilter +{ + function Action (int client); + function Action (int client, const char[] name, LogLevel lvl); + function Action (int client, const char[] name, LogLevel lvl, const char[] msg); +}; diff --git a/sourcemod/scripting/include/log4sp_no_ext/common.inc b/sourcemod/scripting/include/log4sp_no_ext/common.inc index 07ee70e..062ea26 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/common.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/common.inc @@ -31,9 +31,6 @@ #define LOG4SP_LEVEL_SHORT_NAME_OFF "O" -/** - * Log level enum - */ enum LogLevel { LogLevel_Trace = LOG4SP_LEVEL_TRACE, @@ -46,29 +43,50 @@ enum LogLevel LogLevel_Total } -/** - * Pattern time - specific time getting to use for pattern_formatter. - * local time by default - */ enum PatternTimeType { - PatternTimeType_Local, // log localtime - PatternTimeType_Utc // log utc + PatternTimeType_Local, + PatternTimeType_Utc }; -/** - * Async overflow policy - block by default. - */ enum AsyncOverflowPolicy { - AsyncOverflowPolicy_Block, // Block until message can be enqueued. - AsyncOverflowPolicy_OverrunOldest, // Discard oldest message in the queue if full when trying to add new item. - AsyncOverflowPolicy_DiscardNew // Discard new message if the queue is full when trying to add new item. + AsyncOverflowPolicy_Block, + AsyncOverflowPolicy_OverrunOldest, + AsyncOverflowPolicy_DiscardNew } -stock void LogLevelToName(LogLevel lvl, char[] buffer, int maxlen) {} +stock void LogLevelToName(LogLevel lvl, char[] buffer, int maxlen) { + switch (lvl) { + case LogLevel_Trace: strcpy(buffer, LOG4SP_LEVEL_NAME_TRACE); + case LogLevel_Debug: strcpy(buffer, LOG4SP_LEVEL_NAME_DEBUG); + case LogLevel_Info: strcpy(buffer, LOG4SP_LEVEL_NAME_INFO); + case LogLevel_Warn: strcpy(buffer, LOG4SP_LEVEL_NAME_WARN); + case LogLevel_Error: strcpy(buffer, LOG4SP_LEVEL_NAME_ERROR); + case LogLevel_Fatal: strcpy(buffer, LOG4SP_LEVEL_NAME_FATAL); + case LogLevel_Off: strcpy(buffer, LOG4SP_LEVEL_NAME_OFF); + } +} -stock void LogLevelToShortName(LogLevel lvl, char[] buffer, int maxlen) {} +stock void LogLevelToShortName(LogLevel lvl, char[] buffer, int maxlen) { + switch (lvl) { + case LogLevel_Trace: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_TRACE); + case LogLevel_Debug: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_DEBUG); + case LogLevel_Info: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_INFO); + case LogLevel_Warn: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_WARN); + case LogLevel_Error: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_ERROR); + case LogLevel_Fatal: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_FATAL); + case LogLevel_Off: strcpy(buffer, LOG4SP_LEVEL_SHORT_NAME_OFF); + } +} -stock LogLevel NameToLogLevel(const char[] name) { return LogLevel_Off; } +stock LogLevel NameToLogLevel(const char[] name) { + if (StrEqual(name, LOG4SP_LEVEL_NAME_TRACE)) return LogLevel_Trace; + if (StrEqual(name, LOG4SP_LEVEL_NAME_DEBUG)) return LogLevel_Debug; + if (StrEqual(name, LOG4SP_LEVEL_NAME_INFO)) return LogLevel_Info; + if (StrEqual(name, LOG4SP_LEVEL_NAME_WARN) || StrEqual(name, "warning")) return LogLevel_Warn; + if (StrEqual(name, LOG4SP_LEVEL_NAME_ERROR) || StrEqual(name, "err")) return LogLevel_Error; + if (StrEqual(name, LOG4SP_LEVEL_NAME_FATAL) || StrEqual(name, "critical")) return LogLevel_Fatal; + return LogLevel_Off; +} diff --git a/sourcemod/scripting/include/log4sp_no_ext/logger.inc b/sourcemod/scripting/include/log4sp_no_ext/logger.inc index c257df9..8c60ab2 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/logger.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/logger.inc @@ -10,26 +10,38 @@ #include -typeset Log4spErrorCallback +typeset LoggerErrorHandler { - function void (const char[] msg); + function void (Logger logger, const char[] msg); }; static char __message[2048]; methodmap Logger < Handle { - public Logger(const char[] name, Sink[] sinks, int numSinks, bool async=false, AsyncOverflowPolicy policy=AsyncOverflowPolicy_Block) { return view_as(INVALID_HANDLE); } + public Logger(const char[] name, Sink[] sinks, int numSinks, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block) { + return view_as(INVALID_HANDLE); + } - public static Logger Get(const char[] name) { return view_as(INVALID_HANDLE); } + public static Logger Get(const char[] name) { + return view_as(INVALID_HANDLE); + } - public static Logger CreateServerConsoleLogger(const char[] name, bool async=false, AsyncOverflowPolicy policy=AsyncOverflowPolicy_Block) { return view_as(INVALID_HANDLE); } + public static Logger CreateServerConsoleLogger(const char[] name, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block) { + return view_as(INVALID_HANDLE); + } - public static Logger CreateBaseFileLogger(const char[] name, const char[] file, bool truncate=false, bool async=false, AsyncOverflowPolicy policy=AsyncOverflowPolicy_Block) { return view_as(INVALID_HANDLE); } + public static Logger CreateBaseFileLogger(const char[] name, const char[] file, bool truncate = false, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block) { + return view_as(INVALID_HANDLE); + } - public static Logger CreateRotatingFileLogger(const char[] name, const char[] file, int maxFileSize, int maxFiles, bool rotateOnOpen=false, bool async=false, AsyncOverflowPolicy policy=AsyncOverflowPolicy_Block) { return view_as(INVALID_HANDLE); } + public static Logger CreateRotatingFileLogger(const char[] name, const char[] file, int maxFileSize, int maxFiles, bool rotateOnOpen = false, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block) { + return view_as(INVALID_HANDLE); + } - public static Logger CreateDailyFileLogger(const char[] name, const char[] file, int hour=0, int minute=0, bool truncate=false, int maxFiles=0, bool async=false, AsyncOverflowPolicy policy=AsyncOverflowPolicy_Block) { return view_as(INVALID_HANDLE); } + public static Logger CreateDailyFileLogger(const char[] name, const char[] file, int hour = 0, int minute = 0, bool truncate = false, int maxFiles = 0, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block) { + return view_as(INVALID_HANDLE); + } public void GetName(char[] buffer, int maxlen) {} @@ -39,142 +51,191 @@ methodmap Logger < Handle public void SetLevel(LogLevel lvl) {} - public void SetPattern(const char[] pattern, PatternTimeType type=PatternTimeType_Local) {} + public void SetPattern(const char[] pattern, PatternTimeType type = PatternTimeType_Local) {} public bool ShouldLog(LogLevel lvl) { return lvl >= this.GetLevel() && lvl < LogLevel_Off; } public void Log(LogLevel lvl, const char[] msg) { - switch (lvl) { - case LogLevel_Info: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, msg); - case LogLevel_Warn: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, msg); - case LogLevel_Error: LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, msg); - case LogLevel_Fatal: LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, msg); - } + __Log(lvl, msg); + } + public void LogEx(LogLevel lvl, const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 4); + __Log(lvl, __message); } public void LogAmxTpl(LogLevel lvl, const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 4); - switch (lvl) { - case LogLevel_Info: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, __message); - case LogLevel_Warn: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, __message); - case LogLevel_Error: LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, __message); - case LogLevel_Fatal: LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, __message); - } + __Log(lvl, __message); } - // public void LogFmtTpl(LogLevel lvl, const char[] fmt, any ...) {} public void LogSrc(LogLevel lvl, const char[] msg) { - switch (lvl) { - case LogLevel_Info: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, msg); - case LogLevel_Warn: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, msg); - case LogLevel_Error: LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, msg); - case LogLevel_Fatal: LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, msg); - } + __LogSrc(lvl, msg); + } + public void LogSrcEx(LogLevel lvl, const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 4); + __LogSrc(lvl, __message); } public void LogSrcAmxTpl(LogLevel lvl, const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 4); - switch (lvl) { - case LogLevel_Info: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, __message); - case LogLevel_Warn: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, __message); - case LogLevel_Error: LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, __message); - case LogLevel_Fatal: LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, __message); - } + __LogSrc(lvl, __message); } - // public void LogSrcFmtTpl(LogLevel lvl, const char[] fmt, any ...) {} public void LogLoc(const char[] file, int line, const char[] func, LogLevel lvl, const char[] msg) { - switch (lvl) { - case LogLevel_Info: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, msg); - case LogLevel_Warn: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, msg); - case LogLevel_Error: LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, msg); - case LogLevel_Fatal: LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, msg); - } + __LogLoc(file, line, func, lvl, msg); + } + public void LogLocEx(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 7); + __LogLoc(file, line, func, lvl, __message); } public void LogLocAmxTpl(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 7); - switch (lvl) { - case LogLevel_Info: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, __message); - case LogLevel_Warn: LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, __message); - case LogLevel_Error: LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, __message); - case LogLevel_Fatal: LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, __message); - } + __LogLoc(file, line, func, lvl, __message); } - // public void LogLocFmtTpl(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...) {} public void LogStackTrace(LogLevel lvl, const char[] msg) { - LogStackTrace(msg); + __LogStackTrace(lvl, msg); + } + public void LogStackTraceEx(LogLevel lvl, const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 4); + __LogStackTrace(lvl, __message); } public void LogStackTraceAmxTpl(LogLevel lvl, const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 4); - LogStackTrace(__message); + __LogStackTrace(lvl, __message); } - // public void LogStackTraceFmtTpl(LogLevel lvl, const char[] fmt, any ...) {} public void ThrowError(LogLevel lvl, const char[] msg) { - ThrowError(msg); + __ThrowError(lvl, msg); + } + public void ThrowErrorEx(LogLevel lvl, const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 4); + __ThrowError(lvl, __message); } public void ThrowErrorAmxTpl(LogLevel lvl, const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 4); - ThrowError(__message); + __ThrowError(lvl, __message); } - // public void ThrowErrorFmtTpl(LogLevel lvl, const char[] fmt, any ...) {} public void Trace(const char[] msg) {} + public void TraceEx(const char[] fmt, any ...) {} public void TraceAmxTpl(const char[] fmt, any ...) {} - // public void TraceFmtTpl(const char[] fmt, any ...) {} public void Debug(const char[] msg) {} + public void DebugEx(const char[] fmt, any ...) {} public void DebugAmxTpl(const char[] fmt, any ...) {} - // public void DebugFmtTpl(const char[] fmt, any ...) {} public void Info(const char[] msg) { - LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, msg); + __Log(LogLevel_Info, msg); + } + public void InfoEx(const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 3); + __Log(LogLevel_Info, __message); } public void InfoAmxTpl(const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 3); - LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_INFO, __message); + __Log(LogLevel_Info, __message); } - // public void InfoFmtTpl(const char[] fmt, any ...) {} public void Warn(const char[] msg) { - LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, msg); + __Log(LogLevel_Warn, msg); + } + public void WarnEx(const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 3); + __Log(LogLevel_Warn, __message); } public void WarnAmxTpl(const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 3); - LogMessage("[%s] %s", LOG4SP_LEVEL_NAME_WARN, __message); + __Log(LogLevel_Warn, __message); } - // public void WarnFmtTpl(const char[] fmt, any ...) {} public void Error(const char[] msg) { - LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, msg); + __Log(LogLevel_Error, msg); + } + public void ErrorEx(const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 3); + __Log(LogLevel_Error, __message); } public void ErrorAmxTpl(const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 3); - LogError("[%s] %s", LOG4SP_LEVEL_NAME_ERROR, __message); + __Log(LogLevel_Error, __message); } - // public void ErrorFmtTpl(const char[] fmt, any ...) {} public void Fatal(const char[] msg) { - LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, msg); + __Log(LogLevel_Fatal, msg); + } + public void FatalEx(const char[] fmt, any ...) { + VFormat(__message, sizeof(__message), fmt, 3); + __Log(LogLevel_Fatal, __message); } public void FatalAmxTpl(const char[] fmt, any ...) { VFormat(__message, sizeof(__message), fmt, 3); - LogError("[%s] %s", LOG4SP_LEVEL_NAME_FATAL, __message); + __Log(LogLevel_Fatal, __message); } - // public void FatalFmtTpl(const char[] fmt, any ...) {} public void Flush() {} - public LogLevel GetFlushLevel() { return LogLevel_Off; } + public LogLevel GetFlushLevel() { + return LogLevel_Off; + } public void FlushOn(LogLevel lvl) {} - public bool ShouldBacktrace() { return false; } + public bool ShouldBacktrace() { + return false; + } public void EnableBacktrace(int num) {} public void DisableBacktrace() {} public void DumpBacktrace() {} public void AddSink(Sink sink) {} - public bool DropSink(Sink sink) { return false; } + public void DropSink(Sink sink) {} + + public void SetErrorHandler(LoggerErrorHandler handler) {} +} + + +static void __Log(LogLevel lvl, const char[] msg) { + switch (lvl) { + case LogLevel_Info: LogMessage("["... LOG4SP_LEVEL_NAME_INFO ..."] %s", msg); + case LogLevel_Warn: LogMessage("["... LOG4SP_LEVEL_NAME_WARN ..."] %s", msg); + case LogLevel_Error: LogError("["... LOG4SP_LEVEL_NAME_ERROR ..."] %s", msg); + case LogLevel_Fatal: LogError("["... LOG4SP_LEVEL_NAME_FATAL ..."] %s", msg); + } +} + +static void __LogSrc(LogLevel lvl, const char[] msg) { + char file[PLATFORM_MAX_PATH]; + char func[PLATFORM_MAX_PATH]; + int line = 0; + FrameIterator iter = new FrameIterator(); + do + { + iter.GetFilePath(file, sizeof(file)); + iter.GetFunctionName(func, sizeof(func)); + line = iter.LineNumber; + PrintToServer("%s - %s - %d", file, func, line); + } while(iter.Next()); + __Log(lvl, msg); +} + +static void __LogLoc(const char[] file, int line, const char[] func, LogLevel lvl, const char[] msg) { + Format(__message, sizeof(__message), "[%s:%d:%s] %s", file, line, func, msg); + __Log(lvl, __message); +} - public void SetErrorHandler(Log4spErrorCallback callback) {} +static void __LogStackTrace(LogLevel lvl, const char[] msg) { + switch (lvl) { + case LogLevel_Info: LogStackTrace("["... LOG4SP_LEVEL_NAME_INFO ..."] %s", msg); + case LogLevel_Warn: LogStackTrace("["... LOG4SP_LEVEL_NAME_WARN ..."] %s", msg); + case LogLevel_Error: LogStackTrace("["... LOG4SP_LEVEL_NAME_ERROR ..."] %s", msg); + case LogLevel_Fatal: LogStackTrace("["... LOG4SP_LEVEL_NAME_FATAL ..."] %s", msg); + } +} + +static void __ThrowError(LogLevel lvl, const char[] msg) { + switch (lvl) { + case LogLevel_Info: ThrowError("["... LOG4SP_LEVEL_NAME_INFO ..."] %s", msg); + case LogLevel_Warn: ThrowError("["... LOG4SP_LEVEL_NAME_WARN ..."] %s", msg); + case LogLevel_Error: ThrowError("["... LOG4SP_LEVEL_NAME_ERROR ..."] %s", msg); + case LogLevel_Fatal: ThrowError("["... LOG4SP_LEVEL_NAME_FATAL ..."] %s", msg); + } } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/base_file_sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/base_file_sink.inc index ceebcbd..fecdcce 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/base_file_sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/base_file_sink.inc @@ -9,17 +9,11 @@ #include -methodmap BaseFileSinkST < Sink +methodmap BaseFileSink < Sink { - public BaseFileSinkST(const char[] file, bool truncate = false) { return view_as(INVALID_HANDLE); } - - public void GetFilename(char[] buffer, int maxlen) {} -} - - -methodmap BaseFileSinkMT < Sink -{ - public BaseFileSinkMT(const char[] file, bool truncate = false) { return view_as(INVALID_HANDLE); } + public BaseFileSink(const char[] file, bool truncate = false, bool multiThread = false) { + return view_as(INVALID_HANDLE); + } public void GetFilename(char[] buffer, int maxlen) {} } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/client_chat_sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/client_chat_sink.inc index 676a420..9f4987b 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/client_chat_sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/client_chat_sink.inc @@ -9,18 +9,11 @@ #include -typeset ClientChatSinkFilter -{ - function Action (int client); - function Action (int client, const char[] name, LogLevel lvl); - function Action (int client, const char[] name, LogLevel lvl, const char[] msg); -}; - - - methodmap ClientChatSink < Sink { - public ClientchatSinkST() { return view_as(INVALID_HANDLE); } + public ClientChatSink(bool multiThread = false) { + return view_as(INVALID_HANDLE); + } - public void SetFilter(ClientChatSinkFilter filter) {} + public void SetFilter(SinkClientFilter filter) {} } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/client_console_sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/client_console_sink.inc index e792994..da85780 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/client_console_sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/client_console_sink.inc @@ -9,26 +9,11 @@ #include -typeset ClientConsoleSinkFilter +methodmap ClientConsoleSink < Sink { - function Action (int client); - function Action (int client, const char[] name, LogLevel lvl); - function Action (int client, const char[] name, LogLevel lvl, const char[] msg); -}; + public ClientConsoleSink(bool multiThread = false) { + return view_as(INVALID_HANDLE); + } - - -methodmap ClientConsoleSinkST < Sink -{ - public ClientConsoleSinkST() { return view_as(INVALID_HANDLE); } - - public void SetFilter(ClientConsoleSinkFilter filter) {} -} - - -methodmap ClientConsoleSinkMT < Sink -{ - public ClientConsoleSinkMT() { return view_as(INVALID_HANDLE); } - - public void SetFilter(ClientConsoleSinkFilter filter) {} + public void SetFilter(SinkClientFilter filter) {} } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/daily_file_sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/daily_file_sink.inc index 9cab28f..a4f2ddb 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/daily_file_sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/daily_file_sink.inc @@ -9,17 +9,11 @@ #include -methodmap DailyFileSinkST < Sink +methodmap DailyFileSink < Sink { - public DailyFileSinkST(const char[] file, int rotationHour=0, int rotationMinute=0, bool truncate=false, int maxFiles=0) { return view_as(INVALID_HANDLE); } - - public void GetFilename(char[] buffer, int maxlength) {} -} - - -methodmap DailyFileSinkMT < Sink -{ - public DailyFileSinkMT(const char[] file, int rotationHour=0, int rotationMinute=0, bool truncate=false, int maxFiles=0) { return view_as(INVALID_HANDLE); } + public DailyFileSink(const char[] file, int rotationHour = 0, int rotationMinute = 0, bool truncate = false, int maxFiles = 0, bool multiThread = false) { + return view_as(INVALID_HANDLE); + } public void GetFilename(char[] buffer, int maxlength) {} } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/rotating_file_sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/rotating_file_sink.inc index b020180..7f6b3a9 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/rotating_file_sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/rotating_file_sink.inc @@ -9,21 +9,13 @@ #include -methodmap RotatingFileSinkST < Sink +methodmap RotatingFileSink < Sink { - public RotatingFileSinkST(const char[] file, const int maxFileSize, const int maxFiles, bool rotateOnOpen=false) { return view_as(INVALID_HANDLE); } + public RotatingFileSink(const char[] file, const int maxFileSize, const int maxFiles, bool rotateOnOpen = false, bool multiThread = false) { + return view_as(INVALID_HANDLE); + } public void GetFilename(char[] buffer, int maxlength) {} - public void CalcFilename(const char[] file, int index, char[] buffer, int maxlength) {} -} - - -methodmap RotatingFileSinkMT < Sink -{ - public RotatingFileSinkMT(const char[] file, const int maxFileSize, const int maxFiles, bool rotateOnOpen=false) { return view_as(INVALID_HANDLE); } - - public void GetFilename(char[] buffer, int maxlength) {} - - public void CalcFilename(const char[] file, int index, char[] buffer, int maxlength) {} + public static void CalcFilename(const char[] file, int index, char[] buffer, int maxlength) {} } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/server_console_sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/server_console_sink.inc index b8ca00d..c693b1c 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/server_console_sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/server_console_sink.inc @@ -9,13 +9,9 @@ #include -methodmap ServerConsoleSinkST < Sink +methodmap ServerConsoleSink < Sink { - public ServerConsoleSinkST() { return view_as(INVALID_HANDLE); } -} - - -methodmap ServerConsoleSinkMT < Sink -{ - public ServerConsoleSinkMT() { return view_as(INVALID_HANDLE); } + public ServerConsoleSink(bool multiThread = false) { + return view_as(INVALID_HANDLE); + } } diff --git a/sourcemod/scripting/include/log4sp_no_ext/sinks/sink.inc b/sourcemod/scripting/include/log4sp_no_ext/sinks/sink.inc index 785b5de..5e273ae 100644 --- a/sourcemod/scripting/include/log4sp_no_ext/sinks/sink.inc +++ b/sourcemod/scripting/include/log4sp_no_ext/sinks/sink.inc @@ -19,17 +19,21 @@ methodmap Sink < Handle public bool ShouldLog(LogLevel lvl) { return false; } - public void Log(const char[] name, LogLevel lvl, const char[] msg) {} - public void LogAmxTpl(const char[] name, LogLevel lvl, const char[] fmt, any ...) {} - // public void LogFmtTpl(LogLevel lvl, const char[] fmt, any ...) {} - - public void LogSrc(const char[] name, LogLevel lvl, const char[] msg) {} - public void LogSrcAmxTpl(const char[] name, LogLevel lvl, const char[] fmt, any ...) {} - // public void LogSrcFmtTpl(LogLevel lvl, const char[] fmt, any ...) {} - - public void LogLoc(const char[] file, int line, const char[] func, const char[] name, LogLevel lvl, const char[] msg) {} - public void LogLocAmxTpl(const char[] file, int line, const char[] func, const char[] name, LogLevel lvl, const char[] fmt, any ...) {} - // public void LogLocFmtTpl(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...) {} + public void Log(const char[] name, LogLevel lvl, const char[] msg) { + switch (lvl) { + case LogLevel_Info: LogMessage("["... LOG4SP_LEVEL_NAME_INFO ..."] [%s] %s", name, msg); + case LogLevel_Warn: LogMessage("["... LOG4SP_LEVEL_NAME_WARN ..."] [%s] %s", name, msg); + case LogLevel_Error: LogError("["... LOG4SP_LEVEL_NAME_ERROR ..."] [%s] %s", name, msg); + case LogLevel_Fatal: LogError("["... LOG4SP_LEVEL_NAME_FATAL ..."] [%s] %s", name, msg); + } + } public void Flush() {} } + +typeset SinkClientFilter +{ + function Action (int client); + function Action (int client, const char[] name, LogLevel lvl); + function Action (int client, const char[] name, LogLevel lvl, const char[] msg); +}; diff --git a/src/extension.cpp b/src/extension.cpp index eaf25b5..304eeed 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -29,14 +29,16 @@ * Version: $Id$ */ +#include "spdlog/async.h" #include "spdlog/spdlog.h" #include "spdlog/sinks/stdout_sinks.h" -#include "spdlog/sinks/daily_file_sink.h" -#include +#include "extension.h" + +#include "log4sp/adapter/sync_logger.h" +#include "log4sp/logger_register.h" +#include "log4sp/sink_register.h" -#include -#include /** * @file extension.cpp @@ -46,89 +48,42 @@ Log4sp g_Log4sp; /**< Global singleton for extension's main interface */ SMEXT_LINK(&g_Log4sp); -LoggerHandler g_LoggerHandler; -HandleType_t g_LoggerHandleType = 0; - -SinkHandler g_SinkHandler; -HandleType_t g_ServerConsoleSinkHandleType = 0; -HandleType_t g_BaseFileSinkHandleType = 0; -HandleType_t g_RotatingFileSinkHandleType = 0; -HandleType_t g_DailyFileSinkHandleType = 0; -HandleType_t g_ClientConsoleSinkHandleType = 0; -HandleType_t g_ClientChatSinkHandleType = 0; +HandleType_t g_LoggerHandleType = 0; +HandleType_t g_SinkHandleType = 0; bool Log4sp::SDK_OnLoad(char *error, size_t maxlen, bool late) { - HandleError err; - g_LoggerHandleType = handlesys->CreateType("Logger", &g_LoggerHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_LoggerHandleType) - { - snprintf(error, maxlen, "Could not create Logger handle type (err: %d)", err); - return false; - } - - // We don't use inheritance because types only can have up to 15 sub-types. - g_ServerConsoleSinkHandleType = handlesys->CreateType("ServerConsoleSink", &g_SinkHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_ServerConsoleSinkHandleType) - { - snprintf(error, maxlen, "Could not create ServerConsoleSink handle type (err: %d)", err); - return false; - } - - g_BaseFileSinkHandleType = handlesys->CreateType("BaseFileSink", &g_SinkHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_BaseFileSinkHandleType) + // Init handle type { - snprintf(error, maxlen, "Could not create BaseFileSink handle type (err: %d)", err); - return false; - } + HandleAccess access; + handlesys->InitAccessDefaults(nullptr, &access); + access.access[HandleAccess_Delete] = 0; - g_RotatingFileSinkHandleType = handlesys->CreateType("RotatingFileSink", &g_SinkHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_RotatingFileSinkHandleType) - { - snprintf(error, maxlen, "Could not create RotatingFileSink handle type (err: %d)", err); - return false; - } - - g_DailyFileSinkHandleType = handlesys->CreateType("DailyFileSink", &g_SinkHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_DailyFileSinkHandleType) - { - snprintf(error, maxlen, "Could not create DailyFileSink handle type (err: %d)", err); - return false; - } + HandleError err; - g_ClientConsoleSinkHandleType = handlesys->CreateType("ClientConsoleSink", &g_SinkHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_ClientConsoleSinkHandleType) - { - snprintf(error, maxlen, "Could not create ClientConsoleSink handle type (err: %d)", err); - return false; - } + g_LoggerHandleType = handlesys->CreateType("Logger", this, 0, nullptr, &access, myself->GetIdentity(), &err); + if (!g_LoggerHandleType) + { + snprintf(error, maxlen, "Could not create Logger handle type (err: %d)", err); + return false; + } - g_ClientChatSinkHandleType = handlesys->CreateType("ClientChatSink", &g_SinkHandler, 0, NULL, NULL, myself->GetIdentity(), &err); - if (!g_ClientChatSinkHandleType) - { - snprintf(error, maxlen, "Could not create ClientChatSink handle type (err: %d)", err); - return false; + g_SinkHandleType = handlesys->CreateType("Sink", this, 0, nullptr, &access, myself->GetIdentity(), &err); + if (!g_SinkHandleType) + { + snprintf(error, maxlen, "Could not create Sink handle type (err: %d)", err); + return false; + } } - sharesys->AddNatives(myself, CommonNatives); - sharesys->AddNatives(myself, LoggerNatives); - sharesys->AddNatives(myself, SinkNatives); - sharesys->AddNatives(myself, ServerConsoleSinkNatives); - sharesys->AddNatives(myself, BaseFileSinkNatives); - sharesys->AddNatives(myself, RotatingFileSinkNatives); - sharesys->AddNatives(myself, DailyFileSinkNatives); - sharesys->AddNatives(myself, ClientConsoleSinkNatives); - sharesys->AddNatives(myself, ClientChatSinkNatives); - - if (!rootconsole->AddRootConsoleCommand3("log4sp", "Manager Logging For SourcePawn", this)) + // Init console command + if (!rootconsole->AddRootConsoleCommand3(SMEXT_CONF_LOGTAG, "Logging For SourcePawn command menu", this)) { snprintf(error, maxlen, "Could not add root console commmand 'log4sp'."); return false; } - sharesys->RegisterLibrary(myself, "log4sp"); - // Init Global Thread Pool { const char *queueSizeStr = smutils->GetCoreConfigValue("Log4sp_ThreadPoolQueueSize"); @@ -137,75 +92,92 @@ bool Log4sp::SDK_OnLoad(char *error, size_t maxlen, bool late) const char *threadCountStr = smutils->GetCoreConfigValue("Log4sp_ThreadPoolThreadCount"); auto threadCount = threadCountStr != nullptr ? static_cast(atoi(threadCountStr)) : static_cast(1); - // rootconsole->ConsolePrint("Thread Pool: queue size = %d.", queueSize); - // rootconsole->ConsolePrint("Thread Pool: thread count = %d.", threadCount); - spdlog::init_thread_pool(queueSize, threadCount); } // Init Default Logger { - auto consoleSink = std::make_shared(); - consoleSink->set_pattern("[%H:%M:%S.%e] [%n] [%l] %v"); + auto sink = std::make_shared(); + auto logger = std::make_shared(SMEXT_CONF_LOGTAG, sink); - char filepath[PLATFORM_MAX_PATH]; - smutils->BuildPath(Path_SM, filepath, sizeof(filepath), "logs/log4sp.log"); + sink->set_pattern("[%H:%M:%S.%e] [%n] [%l] %v"); + spdlog::set_default_logger(logger); - auto dailyFileSink = std::make_shared(filepath, 0, 0); + HandleSecurity sec = {nullptr, myself->GetIdentity()}; - auto sinks = spdlog::sinks_init_list{consoleSink, dailyFileSink}; - auto logger = std::make_shared(SMEXT_CONF_LOGTAG, sinks); + HandleAccess access; + handlesys->InitAccessDefaults(nullptr, &access); + access.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY; - spdlog::set_default_logger(logger); + HandleError err; + + auto loggerAdapter = log4sp::sync_logger::create(logger, &sec, &access, &err); + if (loggerAdapter == nullptr) + { + snprintf(error, maxlen, "Could not create default logger handle. (err=%d)", err); + return false; + } + + logger->set_level(spdlog::level::trace); } + sharesys->AddNatives(myself, CommonNatives); + sharesys->AddNatives(myself, LoggerNatives); + sharesys->AddNatives(myself, SinkNatives); + sharesys->AddNatives(myself, BaseFileSinkNatives); + sharesys->AddNatives(myself, ClientChatSinkNatives); + sharesys->AddNatives(myself, ClientConsoleSinkNatives); + sharesys->AddNatives(myself, DailyFileSinkNatives); + sharesys->AddNatives(myself, RotatingFileSinkNatives); + sharesys->AddNatives(myself, ServerConsoleSinkNatives); + + sharesys->RegisterLibrary(myself, SMEXT_CONF_LOGTAG); + rootconsole->ConsolePrint("****************** log4sp.ext initialize complete! ******************"); return true; } void Log4sp::SDK_OnUnload() { - log4sp::logger_handle_manager::instance().shutdown(); - log4sp::sink_handle_manager::instance().shutdown(); + log4sp::logger_register::instance().shutdown(); + log4sp::sink_register::instance().shutdown(); handlesys->RemoveType(g_LoggerHandleType, myself->GetIdentity()); + handlesys->RemoveType(g_SinkHandleType, myself->GetIdentity()); - handlesys->RemoveType(g_ServerConsoleSinkHandleType, myself->GetIdentity()); - handlesys->RemoveType(g_BaseFileSinkHandleType, myself->GetIdentity()); - handlesys->RemoveType(g_RotatingFileSinkHandleType, myself->GetIdentity()); - handlesys->RemoveType(g_DailyFileSinkHandleType, myself->GetIdentity()); - handlesys->RemoveType(g_ClientConsoleSinkHandleType, myself->GetIdentity()); - handlesys->RemoveType(g_ClientChatSinkHandleType, myself->GetIdentity()); - - rootconsole->RemoveRootConsoleCommand("log4sp", this); + rootconsole->RemoveRootConsoleCommand(SMEXT_CONF_LOGTAG, this); spdlog::shutdown(); } -void LoggerHandler::OnHandleDestroy(HandleType_t type, void *object) +void Log4sp::OnHandleDestroy(HandleType_t type, void *object) { - auto logger = static_cast(object); - - if (spdlog::should_log(spdlog::level::trace)) + if (type == g_LoggerHandleType) { - auto data = log4sp::logger_handle_manager::instance().get_data(logger->name()); - SPDLOG_TRACE("Destroy a logger handle. (name='{}', hdl={:X}, ptr={})", logger->name(), static_cast(data->handle()), fmt::ptr(object)); - } + auto loggerAdapterRaw = static_cast(object); - log4sp::logger_handle_manager::instance().drop(logger->name()); -} + if (spdlog::should_log(spdlog::level::trace)) + { + auto logger = loggerAdapterRaw->raw(); + SPDLOG_TRACE("Destroy a logger handle. (name='{}', hdl={:X}, ptr={})", logger->name(), static_cast(loggerAdapterRaw->handle()), fmt::ptr(object)); + } -void SinkHandler::OnHandleDestroy(HandleType_t type, void *object) -{ - spdlog::sinks::sink *sink = static_cast(object); + log4sp::logger_register::instance().drop(loggerAdapterRaw->raw()->name()); + return; + } - if (spdlog::should_log(spdlog::level::trace)) + if (type == g_SinkHandleType) { - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - SPDLOG_TRACE("Destroy a sink handle. (type={}, hdl={:X}, ptr={})", data->handle_type(), static_cast(data->handle()), fmt::ptr(object)); - } + auto sinkAdapterRaw = static_cast(object); - log4sp::sink_handle_manager::instance().drop(sink); + if (spdlog::should_log(spdlog::level::trace)) + { + SPDLOG_TRACE("Destroy a sink handle. (hdl={:X}, ptr={})", static_cast(sinkAdapterRaw->handle()), fmt::ptr(object)); + } + + log4sp::sink_register::instance().drop(sinkAdapterRaw); + return; + } } void Log4sp::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *args) @@ -218,30 +190,30 @@ void Log4sp::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *args) rootconsole->ConsolePrint("Usage: sm log4sp [arguments]"); // rootconsole->DrawGenericOption("list", "Show all loggers name."); // ref: https://github.com/gabime/spdlog/issues/180 - rootconsole->DrawGenericOption("get_lvl", "Get a logger logging level."); - rootconsole->DrawGenericOption("set_lvl", "Set a logger logging level. [trace, debug, info, warn, error, fatal, off]"); - rootconsole->DrawGenericOption("set_pattern", "Change a logger log pattern."); - rootconsole->DrawGenericOption("should_log", "Get whether logger is enabled at the given level."); - rootconsole->DrawGenericOption("log", "Logging a Message."); - rootconsole->DrawGenericOption("flush", "Manual flush logger contents."); - rootconsole->DrawGenericOption("get_flush_lvl", "Get the minimum log level that will trigger automatic flush."); - rootconsole->DrawGenericOption("set_flush_lvl", "Set the minimum log level that will trigger automatic flush. [trace, debug, info, warn, error, fatal, off]"); - rootconsole->DrawGenericOption("should_bt", "Create new backtrace sink and move to it all our child sinks."); - rootconsole->DrawGenericOption("enable_bt", "Create new backtrace sink and move to it all our child sinks."); - rootconsole->DrawGenericOption("disable_bt", "Restore orig sinks and level and delete the backtrace sink."); - rootconsole->DrawGenericOption("dump_bt", "Dump the backtrace of logged messages in the logger."); + rootconsole->DrawGenericOption("get_lvl", "Gets a logger log level."); + rootconsole->DrawGenericOption("set_lvl", "Sets a logger log level. [trace, debug, info, warn, error, fatal, off]"); + rootconsole->DrawGenericOption("set_pattern", "Sets formatting for the sinks in a logger."); + rootconsole->DrawGenericOption("should_log", "Gets a logger whether logging is enabled for the given log level."); + rootconsole->DrawGenericOption("log", "Use a logger to log a message."); + rootconsole->DrawGenericOption("flush", "Manual flush a logger contents."); + rootconsole->DrawGenericOption("get_flush_lvl", "Gets the minimum log level that will trigger automatic flush."); + rootconsole->DrawGenericOption("set_flush_lvl", "Sets the minimum log level that will trigger automatic flush. [trace, debug, info, warn, error, fatal, off]"); + rootconsole->DrawGenericOption("should_bt", "Gets whether backtrace logging is enabled."); + rootconsole->DrawGenericOption("enable_bt", "Create new backtrace sink and move to it all our child sinks."); + rootconsole->DrawGenericOption("disable_bt", "Restore original sinks and level and delete the backtrace sink."); + rootconsole->DrawGenericOption("dump_bt", "Dump log messages stored in the backtrace ring buffer."); return; } const char *name = args->Arg(3); - auto data = log4sp::logger_handle_manager::instance().get_data(name); - if (data == nullptr) + auto loggerAdapter = log4sp::logger_register::instance().get(name); + if (loggerAdapter == nullptr) { rootconsole->ConsolePrint("[SM] Logger with name '%s' does not exists.", name); return; } - auto logger = data->logger(); + auto logger = loggerAdapter->raw(); const char *func = args->Arg(2); if (!strcmp(func, "get_lvl")) diff --git a/src/extension.h b/src/extension.h index a531b0b..49b8fad 100644 --- a/src/extension.h +++ b/src/extension.h @@ -42,7 +42,7 @@ * @brief Implementation of the logger in SourcePawn Extension. * Note: Uncomment one of the pre-defined virtual functions in order to use it. */ -class Log4sp : public SDKExtension, public IRootConsoleCommand +class Log4sp : public SDKExtension, public IHandleTypeDispatch, public IRootConsoleCommand { public: /** @@ -113,16 +113,6 @@ class Log4sp : public SDKExtension, public IRootConsoleCommand //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen); #endif -public: - /** - * @brief Handles a root console menu action. - */ - void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *args); -}; - - -class LoggerHandler : public IHandleTypeDispatch -{ public: /** * @brief Called when destroying a handle. Must be implemented. @@ -131,41 +121,26 @@ class LoggerHandler : public IHandleTypeDispatch * @param object Handle internal object. */ void OnHandleDestroy(HandleType_t type, void *object); -}; -class SinkHandler : public IHandleTypeDispatch -{ -public: /** - * @brief Called when destroying a handle. Must be implemented. - * - * @param type Handle type. - * @param object Handle internal object. + * @brief Handles a root console menu action. */ - void OnHandleDestroy(HandleType_t type, void *object); + void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *args); }; extern Log4sp g_Log4sp; -extern LoggerHandler g_LoggerHandler; extern HandleType_t g_LoggerHandleType; - -extern SinkHandler g_SinkHandler; -extern HandleType_t g_ServerConsoleSinkHandleType; -extern HandleType_t g_BaseFileSinkHandleType; -extern HandleType_t g_RotatingFileSinkHandleType; -extern HandleType_t g_DailyFileSinkHandleType; -extern HandleType_t g_ClientConsoleSinkHandleType; -extern HandleType_t g_ClientChatSinkHandleType; +extern HandleType_t g_SinkHandleType; extern const sp_nativeinfo_t CommonNatives[]; extern const sp_nativeinfo_t LoggerNatives[]; extern const sp_nativeinfo_t SinkNatives[]; -extern const sp_nativeinfo_t ServerConsoleSinkNatives[]; extern const sp_nativeinfo_t BaseFileSinkNatives[]; -extern const sp_nativeinfo_t RotatingFileSinkNatives[]; -extern const sp_nativeinfo_t DailyFileSinkNatives[]; -extern const sp_nativeinfo_t ClientConsoleSinkNatives[]; extern const sp_nativeinfo_t ClientChatSinkNatives[]; +extern const sp_nativeinfo_t ClientConsoleSinkNatives[]; +extern const sp_nativeinfo_t DailyFileSinkNatives[]; +extern const sp_nativeinfo_t RotatingFileSinkNatives[]; +extern const sp_nativeinfo_t ServerConsoleSinkNatives[]; #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/src/log4sp/adapter/async_logger-inl.h b/src/log4sp/adapter/async_logger-inl.h new file mode 100644 index 0000000..13f46d1 --- /dev/null +++ b/src/log4sp/adapter/async_logger-inl.h @@ -0,0 +1,116 @@ +#ifndef _LOG4SP_ADAPTER_ASYNC_LOGGER_INL_H_ +#define _LOG4SP_ADAPTER_ASYNC_LOGGER_INL_H_ + +#include "spdlog/sinks/dist_sink.h" + +#include "log4sp/utils.h" +#include "log4sp/logger_register.h" +#include "log4sp/adapter/async_logger.h" + + +namespace log4sp { + +inline std::shared_ptr async_logger::create(std::shared_ptr logger, + IPluginContext *ctx) { + HandleSecurity security = {nullptr, myself->GetIdentity()}; + HandleError error; + + std::shared_ptr logger_adapter = create(logger, &security, nullptr, &error); + if (logger_adapter == nullptr) { + ctx->ReportError("SM Error! Allocation of asynchronous logger handle failed. (err=%d)", error); + return nullptr; + } + + return logger_adapter; +} + +inline std::shared_ptr async_logger::create(std::shared_ptr logger, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error) { + // 1. 创建适配器 + // auto logger_adapter = std::make_shared(logger); + auto logger_adapter = std::shared_ptr(new async_logger(logger)); + + // 2. 为适配器创建 handle + Handle_t handle = handlesys->CreateHandleEx(g_LoggerHandleType, logger_adapter.get(), security, access, error); + if (handle == BAD_HANDLE) { + return nullptr; + } + + // 3. 自定义 (适配) sinks - AddSink / DropSink + // ! 必须保证第一个 sink 是 dist_sink_mt(否则 add_sink/remove_sink 时会造成崩溃) + auto dist_sink = std::dynamic_pointer_cast(logger->sinks().front()); + if (dist_sink == nullptr) { + dist_sink = std::make_shared(); + for (auto sink : logger->sinks()) { + dist_sink->add_sink(sink); + } + + logger->sinks().clear(); + logger->sinks().push_back(dist_sink); + } + + // 4. 自定义 (适配) error handler + logger->set_error_handler([logger_adapter](const std::string &msg) { + logger_adapter->error_handler(msg); + }); + + // 5. 保存 handle + logger_adapter->handle_ = handle; + + // 6. 注册适配器到 logger register + logger_register::instance().register_logger(logger_adapter); + return logger_adapter; +} + +inline void async_logger::add_sink(spdlog::sink_ptr sink) { + auto dist_sink = std::static_pointer_cast(raw_->sinks().front()); + dist_sink->add_sink(sink); +} + +inline void async_logger::remove_sink(spdlog::sink_ptr sink) { + auto dist_sink = std::static_pointer_cast(raw_->sinks().front()); + dist_sink->remove_sink(sink); +} + +inline void async_logger::set_error_forward(IChangeableForward *forward) { + std::lock_guard lock(error_handler_mutex_); + if (error_forward_ != nullptr) { + forwards->ReleaseForward(error_forward_); + } + error_forward_ = forward; +} + +inline void async_logger::error_handler(const std::string &msg) { + std::lock_guard lock(error_handler_mutex_); + if (error_forward_ != nullptr) { + error_forward_->PushCell(handle_); + error_forward_->PushString(msg.c_str()); + error_forward_->Execute(); + } else { + using std::chrono::system_clock; + static std::chrono::system_clock::time_point last_report_time; + static size_t err_counter = 0; + auto now = system_clock::now(); + err_counter++; + if (now - last_report_time < std::chrono::seconds(1)) { + return; + } + last_report_time = now; + auto tm_time = spdlog::details::os::localtime(system_clock::to_time_t(now)); + char date_buf[64]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); +#if defined(USING_R) && defined(R_R_H) // if in R environment + REprintf("[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, name().c_str(), + msg.c_str()); +#else + std::fprintf(stderr, "[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, + raw_->name().c_str(), msg.c_str()); +#endif + } +} + + +} // namespace log4sp +#endif // _LOG4SP_ADAPTER_ASYNC_LOGGER_INL_H_ diff --git a/src/log4sp/adapter/async_logger.h b/src/log4sp/adapter/async_logger.h new file mode 100644 index 0000000..654d8b0 --- /dev/null +++ b/src/log4sp/adapter/async_logger.h @@ -0,0 +1,45 @@ +#ifndef _LOG4SP_ADAPTER_ASYNC_LOGGER_H_ +#define _LOG4SP_ADAPTER_ASYNC_LOGGER_H_ + +#include "spdlog/async_logger.h" + +#include "log4sp/adapter/base_logger.h" + + +namespace log4sp { + +class async_logger final : public base_logger { +public: + static std::shared_ptr create(std::shared_ptr logger, + IPluginContext *ctx); + + static std::shared_ptr create(std::shared_ptr logger, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error); + + const bool is_async() const noexcept override { + return true; + } + + void add_sink(spdlog::sink_ptr sink) override; + + void remove_sink(spdlog::sink_ptr sink) override; + + void set_error_forward(IChangeableForward *forward) override; + + void error_handler(const std::string &msg) override; + +private: + // 不要手动创建! + // 这本该是私有的,但为了方便使用 std::make_shared<> 所以公开 + // 虽然可以使用 std::shared_ptr<> 替代,但是会降低性能 + async_logger(std::shared_ptr logger) : base_logger(std::move(logger)) {} + + std::mutex error_handler_mutex_; +}; + + +} // namespace log4sp +#include "log4sp/adapter/async_logger-inl.h" +#endif // _LOG4SP_ADAPTER_ASYNC_LOGGER_H_ diff --git a/src/log4sp/adapter/base_logger.h b/src/log4sp/adapter/base_logger.h new file mode 100644 index 0000000..4667cc0 --- /dev/null +++ b/src/log4sp/adapter/base_logger.h @@ -0,0 +1,84 @@ +#ifndef _LOG4SP_ADAPTER_BASE_LOGGER_H_ +#define _LOG4SP_ADAPTER_BASE_LOGGER_H_ + +#include "spdlog/logger.h" + +#include "extension.h" + + +namespace log4sp { + +/** + * 受限的适配器设计模式 + * 因为无法继承 spdlog 也无法继承 handle + * 且创建 handle 需要使用对象的指针作为参数,所以 create() 只能是静态的 + * + * Adapter 角色 + * Target: handle + * Client: natives + * Adaptee: raw + * Adapter: 派生类 + */ +class base_logger { +public: + base_logger(std::shared_ptr logger) + : raw_(logger), handle_(BAD_HANDLE), error_forward_(nullptr) {} + + ~base_logger() { + if (error_forward_ != nullptr) { + forwards->ReleaseForward(error_forward_); + } + } + + const std::shared_ptr &raw() const { + return raw_; + } + + const Handle_t handle() const noexcept { + return handle_; + } + + /** + * 成功返回 std::shared_ptr + * 失败返回 nullptr + */ + // static std::shared_ptr create(std::shared_ptr logger, IPluginContext *ctx); + // static std::shared_ptr create(std::shared_ptr logger, const HandleSecurity *security, const HandleAccess *access, HandleError *error); + + static base_logger* read(Handle_t handle, IPluginContext *ctx) { + HandleSecurity security = {nullptr, myself->GetIdentity()}; + base_logger *logger_adapter_raw; + + HandleError error = handlesys->ReadHandle(handle, g_LoggerHandleType, &security, (void **)&logger_adapter_raw); + if (error != HandleError_None) { + ctx->ReportError("Invalid logger handle. (hdl=%X, err=%d)", handle, error); + return nullptr; + } + + return logger_adapter_raw; + } + + virtual const bool is_async() const noexcept = 0; + + // * 以下函数存在并发问题,由 Adapter 重写解决 + + virtual void add_sink(spdlog::sink_ptr sink) = 0; + + virtual void remove_sink(spdlog::sink_ptr sink) = 0; + + // 隐藏 spdlog::logger 的 set_error_forward() + virtual void set_error_forward(IChangeableForward *forward) = 0; + + // 替代 spdlog::logger 的 err_handler_() + // sink_it_() 和 flush_() 将在捕获到异常时调用此函数 + virtual void error_handler(const std::string &msg) = 0; + +protected: + std::shared_ptr raw_; // Adaptee + Handle_t handle_; // Target (调用 create() 创建时自动赋值) + IChangeableForward *error_forward_; // set_error_forward() 赋值 +}; + + +} // namespace log4sp +#endif // _LOG4SP_ADAPTER_BASE_LOGGER_H_ diff --git a/src/log4sp/adapter/base_sink.h b/src/log4sp/adapter/base_sink.h new file mode 100644 index 0000000..fe2dcb4 --- /dev/null +++ b/src/log4sp/adapter/base_sink.h @@ -0,0 +1,63 @@ +#ifndef _LOG4SP_ADAPTER_BASE_SINK_H_ +#define _LOG4SP_ADAPTER_BASE_SINK_H_ + +#include "spdlog/common.h" + +#include "extension.h" + + +namespace log4sp { + +/** + * 受限的适配器设计模式 + * 因为无法继承 spdlog 也无法继承 handle + * 且创建 handle 需要使用对象的指针作为参数,所以 create() 只能是静态的 + * + * Adapter 角色 + * Target: handle + * Client: natives + * Adaptee: raw + * Adapter: 派生类 + */ +class base_sink { +public: + base_sink(spdlog::sink_ptr sink) : raw_(sink) {} + + const spdlog::sink_ptr &raw() const { + return raw_; + } + + const Handle_t handle() const noexcept { + return handle_; + } + + /** + * 成功返回 std::shared_ptr + * 失败返回 nullptr + */ + // static std::shared_ptr create(spdlog::sink_ptr sink, IPluginContext *ctx); + // static std::shared_ptr create(spdlog::sink_ptr sink, const HandleSecurity *security, const HandleAccess *access, HandleError *error); + + static base_sink* read(Handle_t handle, IPluginContext *ctx) { + HandleSecurity security = {nullptr, myself->GetIdentity()}; + base_sink *sink_adapter_raw; + + HandleError error = handlesys->ReadHandle(handle, g_SinkHandleType, &security, (void **)&sink_adapter_raw); + if (error != HandleError_None) { + ctx->ReportError("Invalid sink handle. (hdl=%X, err=%d)", handle, error); + return nullptr; + } + + return sink_adapter_raw; + } + + virtual const bool is_multi_thread() const noexcept = 0; + +protected: + spdlog::sink_ptr raw_; // Adaptee + Handle_t handle_; // Target (调用 create() 创建时自动赋值) +}; + + +} // namespace log4sp +#endif // _LOG4SP_ADAPTER_BASE_SINK_H_ diff --git a/src/log4sp/adapter/multi_thread_sink-inl.h b/src/log4sp/adapter/multi_thread_sink-inl.h new file mode 100644 index 0000000..150afa1 --- /dev/null +++ b/src/log4sp/adapter/multi_thread_sink-inl.h @@ -0,0 +1,49 @@ +#ifndef _LOG4SP_ADAPTER_MULTI_THREAD_SINK_INL_H_ +#define _LOG4SP_ADAPTER_MULTI_THREAD_SINK_INL_H_ + +#include "log4sp/sink_register.h" + +#include "log4sp/adapter/multi_thread_sink.h" + + +namespace log4sp { + +inline std::shared_ptr multi_thread_sink::create(spdlog::sink_ptr sink, + IPluginContext *ctx) { + HandleSecurity security = {nullptr, myself->GetIdentity()}; + HandleError error; + + std::shared_ptr sink_adapter = create(sink, &security, nullptr, &error); + if (sink_adapter == nullptr) { + ctx->ReportError("SM Error! Allocation of multi threaded sink handle failed. (err=%d)", error); + return nullptr; + } + + return sink_adapter; +} + +inline std::shared_ptr multi_thread_sink::create(spdlog::sink_ptr sink, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error) { + // 1. 创建适配器 + // auto sink_adapter = std::make_shared(sink); + auto sink_adapter = std::shared_ptr(new multi_thread_sink(sink)); + + // 2. 为适配器创建 handle + Handle_t handle = handlesys->CreateHandleEx(g_SinkHandleType, sink_adapter.get(), security, access, error); + if (handle == BAD_HANDLE) { + return nullptr; + } + + // 3. 保存 handle + sink_adapter->handle_ = handle; + + // 4. 注册适配器到 logger register + sink_register::instance().register_sink(sink_adapter); + return sink_adapter; +} + + +} // namespace log4sp +#endif // _LOG4SP_ADAPTER_MULTI_THREAD_SINK_INL_H_ diff --git a/src/log4sp/adapter/multi_thread_sink.h b/src/log4sp/adapter/multi_thread_sink.h new file mode 100644 index 0000000..ce07a2e --- /dev/null +++ b/src/log4sp/adapter/multi_thread_sink.h @@ -0,0 +1,33 @@ +#ifndef _LOG4SP_ADAPTER_MULTI_THREAD_SINK_H_ +#define _LOG4SP_ADAPTER_MULTI_THREAD_SINK_H_ + +#include "log4sp/adapter/base_sink.h" + + +namespace log4sp { + +class multi_thread_sink final : public base_sink { +public: + static std::shared_ptr create(spdlog::sink_ptr sink, + IPluginContext *ctx); + + static std::shared_ptr create(spdlog::sink_ptr sink, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error); + + const bool is_multi_thread() const noexcept override { + return true; + } + +private: + // 不要手动创建! + // 这本该是私有的,但为了方便使用 std::make_shared<> 所以公开 + // 虽然可以使用 std::shared_ptr<> 替代,但是会降低性能 + multi_thread_sink(spdlog::sink_ptr sink) : base_sink(std::move(sink)) {} +}; + + +} // namespace log4sp +#include "log4sp/adapter/multi_thread_sink-inl.h" +#endif // _LOG4SP_ADAPTER_MULTI_THREAD_SINK_H_ diff --git a/src/log4sp/adapter/single_thread_sink-inl.h b/src/log4sp/adapter/single_thread_sink-inl.h new file mode 100644 index 0000000..669b621 --- /dev/null +++ b/src/log4sp/adapter/single_thread_sink-inl.h @@ -0,0 +1,50 @@ +#ifndef _LOG4SP_ADAPTER_SINGLE_THREAD_SINK_INL_H_ +#define _LOG4SP_ADAPTER_SINGLE_THREAD_SINK_INL_H_ + +#include "log4sp/sink_register.h" + +#include "log4sp/adapter/single_thread_sink.h" + + +namespace log4sp { + +inline std::shared_ptr single_thread_sink::create(spdlog::sink_ptr sink, + IPluginContext *ctx) { + HandleSecurity security = {nullptr, myself->GetIdentity()}; + HandleError error; + + std::shared_ptr sink_adapter = create(sink, &security, nullptr, &error); + if (sink_adapter == nullptr) { + ctx->ReportError("SM Error! Allocation of single threaded sink handle failed. (err=%d)", error); + return nullptr; + } + + return sink_adapter; + +} + +inline std::shared_ptr single_thread_sink::create(spdlog::sink_ptr sink, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error) { + // 1. 创建适配器 + // auto sink_adapter = std::make_shared(sink); + auto sink_adapter = std::shared_ptr(new single_thread_sink(sink)); + + // 2. 为适配器创建 handle + Handle_t handle = handlesys->CreateHandleEx(g_SinkHandleType, sink_adapter.get(), security, access, error); + if (handle == BAD_HANDLE) { + return nullptr; + } + + // 3. 保存 handle + sink_adapter->handle_ = handle; + + // 4. 注册适配器到 logger register + sink_register::instance().register_sink(sink_adapter); + return sink_adapter; +} + + +} // namespace log4sp +#endif // _LOG4SP_ADAPTER_SINGLE_THREAD_SINK_INL_H_ diff --git a/src/log4sp/adapter/single_thread_sink.h b/src/log4sp/adapter/single_thread_sink.h new file mode 100644 index 0000000..b4f18c5 --- /dev/null +++ b/src/log4sp/adapter/single_thread_sink.h @@ -0,0 +1,33 @@ +#ifndef _LOG4SP_ADAPTER_SINGLE_THREAD_SINK_H_ +#define _LOG4SP_ADAPTER_SINGLE_THREAD_SINK_H_ + +#include "log4sp/adapter/base_sink.h" + + +namespace log4sp { + +class single_thread_sink final : public base_sink { +public: + static std::shared_ptr create(spdlog::sink_ptr sink, + IPluginContext *ctx); + + static std::shared_ptr create(spdlog::sink_ptr sink, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error); + + const bool is_multi_thread() const noexcept override { + return false; + } + +private: + // 不要手动创建! + // 这本该是私有的,但为了方便使用 std::make_shared<> 所以公开 + // 虽然可以使用 std::shared_ptr<> 替代,但是会降低性能 + single_thread_sink(spdlog::sink_ptr sink) : base_sink(std::move(sink)) {} +}; + + +} // namespace log4sp +#include "log4sp/adapter/single_thread_sink-inl.h" +#endif // _LOG4SP_ADAPTER_SINGLE_THREAD_SINK_H_ diff --git a/src/log4sp/adapter/sync_logger-inl.h b/src/log4sp/adapter/sync_logger-inl.h new file mode 100644 index 0000000..86b2fc8 --- /dev/null +++ b/src/log4sp/adapter/sync_logger-inl.h @@ -0,0 +1,99 @@ +#ifndef _LOG4SP_ADAPTER_SYNC_LOGGER_INL_H_ +#define _LOG4SP_ADAPTER_SYNC_LOGGER_INL_H_ + +#include "log4sp/logger_register.h" + +#include "log4sp/adapter/sync_logger.h" + + +namespace log4sp { + +inline std::shared_ptr sync_logger::create(std::shared_ptr logger, + IPluginContext *ctx) { + HandleSecurity security = {nullptr, myself->GetIdentity()}; + HandleError error; + + std::shared_ptr logger_adapter = create(logger, &security, nullptr, &error); + if (logger_adapter == nullptr) { + ctx->ReportError("SM Error! Allocation of synchronous logger handle failed. (err=%d)", error); + return nullptr; + } + + return logger_adapter; +} + +inline std::shared_ptr sync_logger::create(std::shared_ptr logger, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error) { + // 1. 创建适配器 + // auto logger_adapter = std::make_shared(logger); + auto logger_adapter = std::shared_ptr(new sync_logger(logger)); + + // 2. 为适配器创建 handle + Handle_t handle = handlesys->CreateHandleEx(g_LoggerHandleType, logger_adapter.get(), security, access, error); + if (handle == BAD_HANDLE) { + return nullptr; + } + + // 3. 自定义 (适配) error handler + logger->set_error_handler([logger_adapter](const std::string &msg) { + logger_adapter->error_handler(msg); + }); + + // 4. 保存 handle + logger_adapter->handle_ = handle; + + // 5. 注册适配器到 logger register + logger_register::instance().register_logger(logger_adapter); + return logger_adapter; +} + +inline void sync_logger::add_sink(spdlog::sink_ptr sink) { + raw_->sinks().push_back(sink); +} + +inline void sync_logger::remove_sink(spdlog::sink_ptr sink) { + auto begin = raw_->sinks().begin(); + auto end = raw_->sinks().end(); + raw_->sinks().erase(std::remove(begin, end, sink), end); +} + +inline void sync_logger::set_error_forward(IChangeableForward *forward) { + if (error_forward_ != nullptr) { + forwards->ReleaseForward(error_forward_); + } + error_forward_ = forward; +} + +inline void sync_logger::error_handler(const std::string &msg) { + if (error_forward_ != nullptr) { + error_forward_->PushCell(handle_); + error_forward_->PushString(msg.c_str()); + error_forward_->Execute(); + } else { + using std::chrono::system_clock; + static std::chrono::system_clock::time_point last_report_time; + static size_t err_counter = 0; + auto now = system_clock::now(); + err_counter++; + if (now - last_report_time < std::chrono::seconds(1)) { + return; + } + last_report_time = now; + auto tm_time = spdlog::details::os::localtime(system_clock::to_time_t(now)); + char date_buf[64]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); +#if defined(USING_R) && defined(R_R_H) // if in R environment + REprintf("[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, name().c_str(), + msg.c_str()); +#else + std::fprintf(stderr, "[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, + raw_->name().c_str(), msg.c_str()); +#endif + } +} + + +} // namespace log4sp +#endif // _LOG4SP_ADAPTER_SYNC_LOGGER_INL_H_ diff --git a/src/log4sp/adapter/sync_logger.h b/src/log4sp/adapter/sync_logger.h new file mode 100644 index 0000000..ba30dba --- /dev/null +++ b/src/log4sp/adapter/sync_logger.h @@ -0,0 +1,42 @@ +#ifndef _LOG4SP_ADAPTER_SYNC_LOGGER_H_ +#define _LOG4SP_ADAPTER_SYNC_LOGGER_H_ + +#include "log4sp/adapter/base_logger.h" + + +namespace log4sp { +class base_sink; + +class sync_logger final : public base_logger { +public: + static std::shared_ptr create(std::shared_ptr logger, + IPluginContext *ctx); + + static std::shared_ptr create(std::shared_ptr logger, + const HandleSecurity *security, + const HandleAccess *access, + HandleError *error); + + const bool is_async() const noexcept override { + return false; + } + + void add_sink(spdlog::sink_ptr sink) override; + + void remove_sink(spdlog::sink_ptr sink) override; + + void set_error_forward(IChangeableForward *forward) override; + + void error_handler(const std::string &msg) override; + +private: + // 不要手动创建! + // 这本该是私有的,但为了方便使用 std::make_shared<> 所以公开 + // 虽然可以使用 std::shared_ptr<> 替代,但是会降低性能 + sync_logger(std::shared_ptr logger) : base_logger(std::move(logger)) {} +}; + + +} // namespace log4sp +#include "log4sp/adapter/sync_logger-inl.h" +#endif // _LOG4SP_ADAPTER_SYNC_LOGGER_H_ diff --git a/src/log4sp/logger_handle_manager-inl.h b/src/log4sp/logger_handle_manager-inl.h deleted file mode 100644 index ffaa6bd..0000000 --- a/src/log4sp/logger_handle_manager-inl.h +++ /dev/null @@ -1,345 +0,0 @@ -#ifndef _LOG4SP_LOGGER_HANDLE_MANAGER_INL_H_ -#define _LOG4SP_LOGGER_HANDLE_MANAGER_INL_H_ - -#include "spdlog/sinks/dist_sink.h" -#include "spdlog/sinks/stdout_sinks.h" -#include "spdlog/sinks/basic_file_sink.h" -#include "spdlog/sinks/rotating_file_sink.h" -#include "spdlog/sinks/daily_file_sink.h" - -#include - - -namespace log4sp { - -inline logger_handle_manager &logger_handle_manager::instance() -{ - static logger_handle_manager singleInstance; - return singleInstance; -} - -inline logger_handle_data* logger_handle_manager::get_data(const std::string &logger_name) -{ - auto found = logger_datas_.find(logger_name); - return found != logger_datas_.end() ? found->second : nullptr; -} - -inline HandleType_t logger_handle_manager::get_handle_type(Handle_t handle) -{ - return g_LoggerHandleType; -} - -inline spdlog::logger* logger_handle_manager::read_handle(IPluginContext *ctx, Handle_t handle) -{ - auto type = get_handle_type(handle); - if (type == NO_HANDLE_TYPE) - { - ctx->ReportError("Unable to identify the type of logger handle. (hdl=0x%x)", handle); - return nullptr; - } - - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - spdlog::logger *logger; - - auto error = handlesys->ReadHandle(handle, type, &sec, (void **)&logger); - if (error != HandleError_None) - { - ctx->ReportError("Invalid logger handle. (hdl=0x%x, err=%d)", handle, error); - return nullptr; - } - - return logger; -} - -inline void logger_handle_manager::drop(const std::string &logger_name) -{ - auto found = logger_datas_.find(logger_name); - if (found != logger_datas_.end()) - { - delete found->second; - logger_datas_.erase(found); - } -} - -inline void logger_handle_manager::drop_all() -{ - for (auto it = logger_datas_.begin(); it != logger_datas_.end(); ++it) - { - delete it->second; - logger_datas_.erase(it); - } -} - -inline void logger_handle_manager::shutdown() -{ - drop_all(); -} - - -inline logger_handle_data* logger_handle_manager::create_logger_st(IPluginContext *ctx, std::string name, std::vector sinks) -{ - // note: logger name 不可重复 - - auto logger = std::make_shared(name, sinks.begin(), sinks.end()); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - auto handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, false, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - -inline logger_handle_data* logger_handle_manager::create_logger_mt(IPluginContext *ctx, std::string name, std::vector sinks, spdlog::async_overflow_policy policy) -{ - // note: logger name 不可重复 - // note: policy 越界不会异常,但保证参数合法是应该的 - - auto dist_sink = std::make_shared(sinks); - auto logger = std::make_shared(name, dist_sink, spdlog::thread_pool(), policy); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - auto handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, true, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - - -inline logger_handle_data* logger_handle_manager::create_server_console_logger_st(IPluginContext *ctx, std::string name) -{ - // note: logger name 不可重复 - - auto sink = std::make_shared(); - auto logger = std::make_shared(name, sink); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - auto handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded stdout logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, false, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - -inline logger_handle_data* logger_handle_manager::create_server_console_logger_mt(IPluginContext *ctx, std::string name, spdlog::async_overflow_policy policy) -{ - // note: logger name 不可重复 - // note: policy 越界不会异常,但保证参数合法是应该的 - - auto sink = std::make_shared(); - auto sinks = std::vector{sink}; - auto dist_sink = std::make_shared(sinks); - auto logger = std::make_shared(name, dist_sink, spdlog::thread_pool(), policy); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - auto handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded stdout logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, true, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - - -inline logger_handle_data* logger_handle_manager::create_base_file_logger_st(IPluginContext *ctx, std::string name, std::string filename, bool truncate) -{ - // note: logger name 不可重复 - - auto sink = std::make_shared(filename, truncate); - auto logger = std::make_shared(name, sink); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded base file logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, false, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - -inline logger_handle_data* logger_handle_manager::create_base_file_logger_mt(IPluginContext *ctx, std::string name, std::string filename, bool truncate, spdlog::async_overflow_policy policy) -{ - // note: logger name 不可重复 - // note: policy 越界不会异常,但保证参数合法是应该的 - - auto sink = std::make_shared(filename, truncate); - auto sinks = std::vector{sink}; - auto dist_sink = std::make_shared(sinks); - auto logger = std::make_shared(name, dist_sink, spdlog::thread_pool(), policy); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded base file logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, true, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - - -inline logger_handle_data* logger_handle_manager::create_rotating_file_logger_st(IPluginContext *ctx, std::string name, std::string filename, size_t max_file_size, size_t max_files, bool rotate_on_open) -{ - // note: logger name 不可重复 - - auto sink = std::make_shared(filename, max_file_size, max_files, rotate_on_open); - auto logger = std::make_shared(name, sink); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded rotating file logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, false, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - -inline logger_handle_data* logger_handle_manager::create_rotating_file_logger_mt(IPluginContext *ctx, std::string name, std::string filename, size_t max_file_size, size_t max_files, bool rotate_on_open, spdlog::async_overflow_policy policy) -{ - // note: logger name 不可重复 - // note: policy 越界不会异常,但保证参数合法是应该的 - - auto sink = std::make_shared(filename, max_file_size, max_files, rotate_on_open); - auto sinks = std::vector{sink}; - auto dist_sink = std::make_shared(sinks); - auto logger = std::make_shared(name, dist_sink, spdlog::thread_pool(), policy); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded rotating file logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, true, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - - -inline logger_handle_data* logger_handle_manager::create_daily_file_logger_st(IPluginContext *ctx, std::string name, std::string filename, int hour, int minute, bool truncate, uint16_t max_files) -{ - // note: logger name 不可重复 - - auto sink = std::make_shared(filename, hour, minute, truncate, max_files); - auto logger = std::make_shared(name, sink); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded daily file logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, false, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - -inline logger_handle_data* logger_handle_manager::create_daily_file_logger_mt(IPluginContext *ctx, std::string name, std::string filename, int hour, int minute, bool truncate, uint16_t max_files, spdlog::async_overflow_policy policy) -{ - // note: logger name 不可重复 - // note: policy 越界不会异常,但保证参数合法是应该的 - - auto sink = std::make_shared(filename, hour, minute, truncate, max_files); - auto sinks = std::vector{sink}; - auto dist_sink = std::make_shared(sinks); - auto logger = std::make_shared(name, dist_sink, spdlog::thread_pool(), policy); - - auto type = g_LoggerHandleType; - auto obj = logger.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, nullptr, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded daily file logger handle failed. (error %d)", error); - return nullptr; - } - - auto data = new logger_handle_data{logger, true, handle, type, nullptr}; - register_logger_handle_(logger->name(), data); - return data; -} - - -inline void logger_handle_manager::register_logger_handle_(const std::string &key, log4sp::logger_handle_data *data) -{ - logger_datas_.insert(std::make_pair(key, data)); -} - - -} // namespace log4sp - - -#endif // _LOG4SP_LOGGER_HANDLE_MANAGER_INL_H_ diff --git a/src/log4sp/logger_handle_manager.h b/src/log4sp/logger_handle_manager.h deleted file mode 100644 index 466b705..0000000 --- a/src/log4sp/logger_handle_manager.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef _LOG4SP_LOGGER_HANDLE_MANAGER_H_ -#define _LOG4SP_LOGGER_HANDLE_MANAGER_H_ - -#include - -#include "spdlog/async.h" - -#include - - -namespace log4sp { - -struct logger_handle_data { -public: - const std::shared_ptr &logger() const noexcept { - return logger_; - } - - const bool is_multi_threaded() const noexcept { - return is_multi_threaded_; - } - - const Handle_t handle() const noexcept { - return handle_; - } - - const HandleType_t handle_type() const noexcept { - return handle_type_; - } - - const IChangeableForward& error_forward() const noexcept { - return *error_forward_; - } - - void set_error_handler(IChangeableForward *forward) { - if (error_forward_ != NULL) - { - forwards->ReleaseForward(error_forward_); - } - - error_forward_ = forward; - } - -private: - logger_handle_data(std::shared_ptr logger, bool is_multi_threaded, Handle_t handle, HandleType_t type, IChangeableForward *forward) - : logger_(logger), is_multi_threaded_(is_multi_threaded), handle_(handle), handle_type_(type), error_forward_(forward) {} - - ~logger_handle_data() { - if (error_forward_ != NULL) { - forwards->ReleaseForward(error_forward_); - } - } - - std::shared_ptr logger_;// 智能指针(管理生命周期) - bool is_multi_threaded_; - Handle_t handle_; - HandleType_t handle_type_; - IChangeableForward *error_forward_; // 只有在调用 SetErrorHandler 后才不为 NULL - - friend class logger_handle_manager; -}; - - - -/** - * 由于 sourcemod 的 handlesys 只提供了通过 handle 查找原始指针的方法,所以添加此类用于反向查找 handle 数据。 - * 还封装了工厂方法,所有 native 中创建的 logger handle 都使用这些工厂方法来创建对象,方便管理生命周期。 - */ -class logger_handle_manager -{ -public: - static logger_handle_manager &instance(); - - /** - * 用于 - * - 根据 name 获取 完整数据。 - * - 检查 logger name 是否已存在。 - * - logger 原始指针的接口不足以满足需求时。 - * - * @return logger_handle_data 或 nullptr 代表没有名为 logger_name 的数据 - */ - logger_handle_data* get_data(const std::string &logger_name); - - /** - * 根据 handle 获取 handle type。 - * @note 目前只有一种 logger handle type - * - * @return handle 或 NO_HANDLE_TYPE 代表参数 handle 无效 - */ - HandleType_t get_handle_type(Handle_t handle); - - /** - * 根据 handle 获取 指针。 - * 如果 handle 无效,则会中断 sourcepawn 代码,并记录错误信息。 - * - * @return logger 或 nullptr 代表参数 handle 无效 - */ - spdlog::logger* read_handle(IPluginContext *ctx, Handle_t handle); - - /** - * 应该只在 LoggerHandler::OnHandleDestroy 中使用 - * 默认 logger 不应该触发 LoggerHandler::OnHandleDestroy - */ - void drop(const std::string &logger_name); - - /** - * 应该只在 Log4sp::SDK_OnUnload 中使用 - */ - void drop_all(); - - /** - * 应该只在 Log4sp::SDK_OnUnload 中使用 - * drop_all() 的包装器 - */ - void shutdown(); - - logger_handle_data* create_logger_st(IPluginContext *ctx, std::string name, std::vector sinks); - logger_handle_data* create_logger_mt(IPluginContext *ctx, std::string name, std::vector sinks, spdlog::async_overflow_policy policy = spdlog::async_overflow_policy::block); - - logger_handle_data* create_server_console_logger_st(IPluginContext *ctx, std::string name); - logger_handle_data* create_server_console_logger_mt(IPluginContext *ctx, std::string name, spdlog::async_overflow_policy policy = spdlog::async_overflow_policy::block); - - logger_handle_data* create_base_file_logger_st(IPluginContext *ctx, std::string name, std::string filename, bool truncate = false); - logger_handle_data* create_base_file_logger_mt(IPluginContext *ctx, std::string name, std::string filename, bool truncate = false, spdlog::async_overflow_policy policy = spdlog::async_overflow_policy::block); - - logger_handle_data* create_rotating_file_logger_st(IPluginContext *ctx,std::string name,std::string filename,size_t max_file_size, size_t max_files, bool rotate_on_open = false); - logger_handle_data* create_rotating_file_logger_mt(IPluginContext *ctx,std::string name,std::string filename,size_t max_file_size, size_t max_files, bool rotate_on_open = false, spdlog::async_overflow_policy policy = spdlog::async_overflow_policy::block); - - logger_handle_data* create_daily_file_logger_st(IPluginContext *ctx, std::string name, std::string filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0); - logger_handle_data* create_daily_file_logger_mt(IPluginContext *ctx, std::string name, std::string filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0, spdlog::async_overflow_policy policy = spdlog::async_overflow_policy::block); - -private: - logger_handle_manager() {} - - void register_logger_handle_(const std::string &key, log4sp::logger_handle_data *data); - - // 用于根据 logger 指针查找完整信息 - // 参考与 , 但速度应该更快,因为单线程不需要锁 - std::unordered_map logger_datas_; - - // 用于根据 handle 查找 type - // std::unordered_map handle_types_; -}; - -} // namespace log4sp - -#include "logger_handle_manager-inl.h" - -#endif // _LOG4SP_LOGGER_HANDLE_MANAGER_H_ diff --git a/src/log4sp/logger_register.h b/src/log4sp/logger_register.h new file mode 100644 index 0000000..5dca6ba --- /dev/null +++ b/src/log4sp/logger_register.h @@ -0,0 +1,64 @@ +#ifndef _LOG4SP_LOGGER_REGISTER_H_ +#define _LOG4SP_LOGGER_REGISTER_H_ + +#include + +#include "extension.h" + +#include "log4sp/adapter/base_logger.h" + + +namespace log4sp { + +/** + * 参考 "spdlog/details/registry.h" + * 但速度应该更快,因为单线程不需要锁 + */ +class logger_register final { +public: + static logger_register &instance() { + static logger_register singleInstance; + return singleInstance; + } + + void register_logger(std::shared_ptr logger_adapter) { + loggers_[logger_adapter->raw()->name()] = std::move(logger_adapter); + } + + std::shared_ptr get(const std::string &name) { + auto found = loggers_.find(name); + return found == loggers_.end() ? nullptr : found->second; + } + + /** + * 应该只在 LoggerHandler::OnHandleDestroy 中使用 + */ + void drop(const std::string &name) { + loggers_.erase(name); + } + + /** + * 应该只在 Log4sp::SDK_OnUnload 中使用 + */ + void drop_all() { + loggers_.clear(); + } + + /** + * 应该只在 Log4sp::SDK_OnUnload 中使用 + * drop_all() 的包装器 + */ + void shutdown() { + drop_all(); + } + +private: + logger_register() {} + ~logger_register() {} + + std::unordered_map> loggers_; +}; + + +} // namespace log4sp +#endif // _LOG4SP_LOGGER_REGISTER_H_ diff --git a/src/log4sp/sink_handle_manager-inl.h b/src/log4sp/sink_handle_manager-inl.h deleted file mode 100644 index 2301750..0000000 --- a/src/log4sp/sink_handle_manager-inl.h +++ /dev/null @@ -1,343 +0,0 @@ -#ifndef _LOG4SP_SINK_HANDLE_MANAGER_INL_H_ -#define _LOG4SP_SINK_HANDLE_MANAGER_INL_H_ - -#include "spdlog/sinks/stdout_sinks.h" -#include "spdlog/sinks/basic_file_sink.h" -#include "spdlog/sinks/daily_file_sink.h" -#include "spdlog/sinks/rotating_file_sink.h" - -#include -#include -#include - - -namespace log4sp { - -inline sink_handle_manager &sink_handle_manager::instance() -{ - static sink_handle_manager singleInstance; - return singleInstance; -} - -inline sink_handle_data* sink_handle_manager::get_data(spdlog::sinks::sink *sink) -{ - auto found = sink_datas_.find(sink); - return found != sink_datas_.end() ? found->second : nullptr; -} - -inline HandleType_t sink_handle_manager::get_handle_type(Handle_t handle) -{ - auto found = handle_types_.find(handle); - return found != handle_types_.end() ? found->second : NO_HANDLE_TYPE; -} - -inline spdlog::sinks::sink* sink_handle_manager::read_handle(IPluginContext *ctx, Handle_t handle) -{ - auto type = get_handle_type(handle); - if (type == NO_HANDLE_TYPE) - { - ctx->ReportError("Unable to identify the type of sink handle. (handle=0x%x)", handle); - return nullptr; - } - - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - spdlog::sinks::sink *sink; - - auto error = handlesys->ReadHandle(handle, type, &sec, (void **)&sink); - if (error != HandleError_None) - { - ctx->ReportError("Invalid sink handle. (handle=0x%x, error=%d)", handle, error); - return nullptr; - } - - return sink; -} - -inline void sink_handle_manager::drop(spdlog::sinks::sink *sink) -{ - auto it = sink_datas_.find(sink); - if (it != sink_datas_.end()) - { - handle_types_.erase(it->second->handle()); - sink_datas_.erase(it); - } -} - -inline void sink_handle_manager::drop_all() -{ - sink_datas_.clear(); - handle_types_.clear(); -} - -inline void sink_handle_manager::shutdown() -{ - drop_all(); -} - - -inline sink_handle_data* sink_handle_manager::create_server_console_sink_st(IPluginContext *ctx) -{ - auto sink = std::make_shared(); - - auto type = g_ServerConsoleSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded server console sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, false, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_server_console_sink_mt(IPluginContext *ctx) -{ - auto sink = std::make_shared(); - - auto type = g_ServerConsoleSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded server console sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, true, handle, type}; - register_sink_handle_(obj, data); - return data; -} - - -inline sink_handle_data* sink_handle_manager::create_base_file_sink_st(IPluginContext *ctx, const char *filename, bool truncate) -{ - auto sink = std::make_shared(filename, truncate); - - auto type = g_BaseFileSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded base file sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, false, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_base_file_sink_mt(IPluginContext *ctx, const char *filename, bool truncate) -{ - auto sink = std::make_shared(filename, truncate); - - auto type = g_BaseFileSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded base file sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, true, handle, type}; - register_sink_handle_(obj, data); - return data; -} - - -inline sink_handle_data* sink_handle_manager::create_rotating_file_sink_st(IPluginContext *ctx, const char *base_filename, size_t max_size, size_t max_files, bool rotate_on_open) -{ - auto sink = std::make_shared(base_filename, max_size, max_files, rotate_on_open); - - auto type = g_RotatingFileSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded rotating file sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, false, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_rotating_file_sink_mt(IPluginContext *ctx, const char *base_filename, size_t max_size, size_t max_files, bool rotate_on_open) -{ - auto sink = std::make_shared(base_filename, max_size, max_files, rotate_on_open); - - auto type = g_RotatingFileSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded rotating file sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, true, handle, type}; - register_sink_handle_(obj, data); - return data; -} - - -inline sink_handle_data* sink_handle_manager::create_daily_file_sink_st(IPluginContext *ctx, const char *base_filename, int rotation_hour, int rotation_minute, bool truncate, uint16_t max_files) -{ - auto sink = std::make_shared(base_filename, rotation_hour, rotation_minute, truncate, max_files); - - auto type = g_DailyFileSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded daily file sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, false, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_daily_file_sink_mt(IPluginContext *ctx, const char *base_filename, int rotation_hour, int rotation_minute, bool truncate, uint16_t max_files) -{ - auto sink = std::make_shared(base_filename, rotation_hour, rotation_minute, truncate, max_files); - - auto type = g_DailyFileSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded daily file sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, true, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_client_console_sink_st(IPluginContext *ctx) -{ - auto sink = std::make_shared(); - - auto type = g_ClientConsoleSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded client console sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, false, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_client_console_sink_mt(IPluginContext *ctx) -{ - auto sink = std::make_shared(); - - auto type = g_ClientConsoleSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded client console sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, true, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_client_chat_sink_st(IPluginContext *ctx) -{ - auto sink = std::make_shared(); - - auto type = g_ClientChatSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of single threaded client chat sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, false, handle, type}; - register_sink_handle_(obj, data); - return data; -} - -inline sink_handle_data* sink_handle_manager::create_client_chat_sink_mt(IPluginContext *ctx) -{ - auto sink = std::make_shared(); - - auto type = g_ClientChatSinkHandleType; - auto obj = sink.get(); - auto sec = HandleSecurity(ctx->GetIdentity(), myself->GetIdentity()); - HandleError error; - - Handle_t handle = handlesys->CreateHandleEx(type, obj, &sec, NULL, &error); - if (handle == BAD_HANDLE) - { - ctx->ReportError("Allocation of multi threaded client chat sink handle failed. (error %d)", error); - return nullptr; - } - - auto data = new sink_handle_data{sink, true, handle, type}; - register_sink_handle_(obj, data); - return data; -} - - -inline void sink_handle_manager::register_sink_handle_(spdlog::sinks::sink *key, sink_handle_data* data) -{ - sink_datas_.insert(std::pair{key, data}); - handle_types_.insert(std::pair{data->handle(), data->handle_type()}); -} - - -} // namespace log4sp - -#endif // _LOG4SP_SINK_HANDLE_MANAGER_INL_H_ diff --git a/src/log4sp/sink_handle_manager.h b/src/log4sp/sink_handle_manager.h deleted file mode 100644 index 7347cce..0000000 --- a/src/log4sp/sink_handle_manager.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef _LOG4SP_SINK_HANDLE_MANAGER_H_ -#define _LOG4SP_SINK_HANDLE_MANAGER_H_ - -#include - -#include - - -namespace log4sp { - -struct sink_handle_data { -public: - const spdlog::sink_ptr &sink_ptr() const noexcept { - return sink_ptr_; - } - - const bool is_multi_threaded() const noexcept { - return is_multi_threaded_; - } - - const Handle_t handle() const noexcept { - return handle_; - } - - const HandleType_t handle_type() const noexcept { - return handle_type_; - } - -private: - sink_handle_data(spdlog::sink_ptr sink, bool is_multi_threaded, Handle_t handle, HandleType_t type) - : sink_ptr_(sink), is_multi_threaded_(is_multi_threaded), handle_(handle), handle_type_(type) {} - - ~sink_handle_data() {} - - spdlog::sink_ptr sink_ptr_; // 智能指针(管理生命周期) - bool is_multi_threaded_; - Handle_t handle_; - HandleType_t handle_type_; - - friend class sink_handle_manager; -}; - - - -/** - * 由于 sourcemod 的 handlesys 只提供了通过 handle 查找原始指针的方法,所以添加此类用于反向查找 handle 数据。 - * 还封装了工厂方法,所有 native 中创建的 sink handle 都使用这些工厂方法来创建对象,方便管理生命周期。 - */ -class sink_handle_manager -{ -public: - static sink_handle_manager &instance(); - - /** - * 用于 - * - 根据 sink 原始指针获取 完整数据。 - * - sink 原始指针的接口不足以满足需求时。 - * - * @return sink_handle_data 或 nullptr 代表参数 sink 无效 - */ - sink_handle_data* get_data(spdlog::sinks::sink *sink); - - /** - * 根据 handle 获取 handle type。 - * - * @return handle 或 NO_HANDLE_TYPE 代表参数 handle 无效 - */ - HandleType_t get_handle_type(Handle_t handle); - - /** - * 根据 handle 获取 原始指针。 - * 如果 handle 无效,则会中断 sourcepawn 代码,并记录错误信息。 - * - * @return sink 原始指针或 nullptr 代表参数 handle 无效 - */ - spdlog::sinks::sink* read_handle(IPluginContext *ctx, Handle_t handle); - - /** - * 应该只在 SinkHandler::OnHandleDestroy 中使用 - */ - void drop(spdlog::sinks::sink *sink); - - /** - * 应该只在 Log4sp::SDK_OnUnload 中使用 - */ - void drop_all(); - - /** - * 应该只在 Log4sp::SDK_OnUnload 中使用 - * drop_all() 的包装器 - */ - void shutdown(); - - sink_handle_data* create_server_console_sink_st(IPluginContext *ctx); - sink_handle_data* create_server_console_sink_mt(IPluginContext *ctx); - - sink_handle_data* create_base_file_sink_st(IPluginContext *ctx, const char *filename, bool truncate = false); - sink_handle_data* create_base_file_sink_mt(IPluginContext *ctx, const char *filename, bool truncate = false); - - sink_handle_data* create_rotating_file_sink_st(IPluginContext *ctx, const char *base_filename, size_t max_size, size_t max_files, bool rotate_on_open = false); - sink_handle_data* create_rotating_file_sink_mt(IPluginContext *ctx, const char *base_filename, size_t max_size, size_t max_files, bool rotate_on_open = false); - - sink_handle_data* create_daily_file_sink_st(IPluginContext *ctx, const char *base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0); - sink_handle_data* create_daily_file_sink_mt(IPluginContext *ctx, const char *base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0); - - sink_handle_data* create_client_console_sink_st(IPluginContext *ctx); - sink_handle_data* create_client_console_sink_mt(IPluginContext *ctx); - - sink_handle_data* create_client_chat_sink_st(IPluginContext *ctx); - sink_handle_data* create_client_chat_sink_mt(IPluginContext *ctx); - -private: - sink_handle_manager() {} - - void register_sink_handle_(spdlog::sinks::sink *key, sink_handle_data *data); - - // 用于根据 sink 查找完整信息 - std::unordered_map sink_datas_; - - // 用于根据 handle 查找 type - std::unordered_map handle_types_; -}; - - -} // namespace log4sp - -#include "sink_handle_manager-inl.h" - -#endif // _LOG4SP_SINK_HANDLE_MANAGER_H_ diff --git a/src/log4sp/sink_register.h b/src/log4sp/sink_register.h new file mode 100644 index 0000000..2e22a95 --- /dev/null +++ b/src/log4sp/sink_register.h @@ -0,0 +1,66 @@ +#ifndef _LOG4SP_SINK_REGISTER_H_ +#define _LOG4SP_SINK_REGISTER_H_ + +#include + +#include "spdlog/common.h" + +#include "extension.h" + +#include "log4sp/adapter/base_sink.h" + + +namespace log4sp { + +/** + * 参考 "spdlog/details/registry.h" + * 但速度应该更快,因为单线程不需要锁 + */ +class sink_register final { +public: + static sink_register &instance() { + static sink_register singleInstance; + return singleInstance; + } + + void register_sink(std::shared_ptr sink_adapter) { + sinks_[sink_adapter.get()] = std::move(sink_adapter); + } + + std::shared_ptr get(base_sink *sink_adapter_raw) { + auto found = sinks_.find(sink_adapter_raw); + return found == sinks_.end() ? nullptr : found->second; + } + + /** + * 应该只在 SinkHandler::OnHandleDestroy 中使用 + */ + void drop(base_sink *sink_adapter_raw) { + sinks_.erase(sink_adapter_raw); + } + + /** + * 应该只在 Log4sp::SDK_OnUnload 中使用 + */ + void drop_all() { + sinks_.clear(); + } + + /** + * 应该只在 Log4sp::SDK_OnUnload 中使用 + * drop_all() 的包装器 + */ + void shutdown() { + drop_all(); + } + +private: + sink_register() {} + ~sink_register() {} + + std::unordered_map> sinks_; +}; + + +} // namespace log4sp +#endif // _LOG4SP_SINK_REGISTER_H_ diff --git a/src/log4sp/sinks/client_chat_sink-inl.h b/src/log4sp/sinks/client_chat_sink-inl.h index e53825f..4cf81af 100644 --- a/src/log4sp/sinks/client_chat_sink-inl.h +++ b/src/log4sp/sinks/client_chat_sink-inl.h @@ -1,7 +1,7 @@ -#ifndef _LOG4SP_CLIENT_CHAT_SINK_INL_H_ -#define _LOG4SP_CLIENT_CHAT_SINK_INL_H_ +#ifndef _LOG4SP_SINKS_CLIENT_CHAT_SINK_INL_H_ +#define _LOG4SP_SINKS_CLIENT_CHAT_SINK_INL_H_ -#include +#include "log4sp/sinks/client_chat_sink.h" namespace log4sp { namespace sinks { @@ -28,7 +28,7 @@ inline bool client_chat_sink::set_player_filter(IPluginFunction *filter) forwards->ReleaseForward(player_filter_forward_); } - player_filter_forward_ = forwards->CreateForwardEx(NULL, ET_Ignore, 4, NULL, Param_Cell, Param_String, Param_Cell, Param_String); + player_filter_forward_ = forwards->CreateForwardEx(nullptr, ET_Ignore, 4, nullptr, Param_Cell, Param_String, Param_Cell, Param_String); if (player_filter_forward_ == nullptr) { return false; @@ -82,9 +82,7 @@ inline void client_chat_sink::sink_it_(const spdlog::details::log_msg &ms } } -} // namespace sinks -} // namespace log4sp - - -#endif // _LOG4SP_CLIENT_CHAT_SINK_INL_H_ +} // namespace sinks +} // namespace log4sp +#endif // _LOG4SP_SINKS_CLIENT_CHAT_SINK_INL_H_ diff --git a/src/log4sp/sinks/client_chat_sink.h b/src/log4sp/sinks/client_chat_sink.h index 50ba7b2..620a944 100644 --- a/src/log4sp/sinks/client_chat_sink.h +++ b/src/log4sp/sinks/client_chat_sink.h @@ -1,5 +1,5 @@ -#ifndef _LOG4SP_CLIENT_CHAT_SINK_H_ -#define _LOG4SP_CLIENT_CHAT_SINK_H_ +#ifndef _LOG4SP_SINKS_CLIENT_CHAT_SINK_H_ +#define _LOG4SP_SINKS_CLIENT_CHAT_SINK_H_ #include "spdlog/details/synchronous_factory.h" #include "spdlog/sinks/base_sink.h" @@ -14,7 +14,6 @@ template class client_chat_sink : public spdlog::sinks::base_sink { public: - client_chat_sink(); ~client_chat_sink(); bool set_player_filter(IPluginFunction *filter); @@ -47,8 +46,7 @@ inline std::shared_ptr client_chat_sink_st() return Factory::template create(); } -} // namespace log4sp -#include "client_chat_sink-inl.h" - -#endif // _LOG4SP_CLIENT_CHAT_SINK_H_ +} // namespace log4sp +#include "log4sp/sinks/client_chat_sink-inl.h" +#endif // _LOG4SP_SINKS_CLIENT_CHAT_SINK_H_ diff --git a/src/log4sp/sinks/client_console_sink-inl.h b/src/log4sp/sinks/client_console_sink-inl.h index 273366f..f062b14 100644 --- a/src/log4sp/sinks/client_console_sink-inl.h +++ b/src/log4sp/sinks/client_console_sink-inl.h @@ -1,7 +1,7 @@ -#ifndef _LOG4SP_CLIENT_CONSOLE_SINK_INL_H_ -#define _LOG4SP_CLIENT_CONSOLE_SINK_INL_H_ +#ifndef _LOG4SP_SINKS_CLIENT_CONSOLE_SINK_INL_H_ +#define _LOG4SP_SINKS_CLIENT_CONSOLE_SINK_INL_H_ -#include +#include "log4sp/sinks/client_console_sink.h" namespace log4sp { namespace sinks { @@ -28,7 +28,7 @@ inline bool client_console_sink::set_player_filter(IPluginFunction *filte forwards->ReleaseForward(player_filter_forward_); // 清空 forward function } - player_filter_forward_ = forwards->CreateForwardEx(NULL, ET_Ignore, 4, NULL, Param_Cell, Param_String, Param_Cell, Param_String); + player_filter_forward_ = forwards->CreateForwardEx(nullptr, ET_Ignore, 4, nullptr, Param_Cell, Param_String, Param_Cell, Param_String); if (player_filter_forward_ == nullptr) { return false; @@ -88,9 +88,7 @@ inline void client_console_sink::flush_() // No need to do anything... } -} // namespace sinks -} // namespace log4sp - - -#endif // _LOG4SP_CLIENT_CONSOLE_SINK_INL_H_ +} // namespace sinks +} // namespace log4sp +#endif // _LOG4SP_SINKS_CLIENT_CONSOLE_SINK_INL_H_ diff --git a/src/log4sp/sinks/client_console_sink.h b/src/log4sp/sinks/client_console_sink.h index 942965c..67cb81a 100644 --- a/src/log4sp/sinks/client_console_sink.h +++ b/src/log4sp/sinks/client_console_sink.h @@ -46,8 +46,7 @@ inline std::shared_ptr client_console_logger_st() return Factory::template create(); } -} // namespace log4sp -#include "client_console_sink-inl.h" - -#endif // _LOG4SP_CLIENT_CONSOLE_SINK_H_ +} // namespace log4sp +#include "log4sp/sinks/client_console_sink-inl.h" +#endif // _LOG4SP_CLIENT_CONSOLE_SINK_H_ diff --git a/src/log4sp/utils-inl.h b/src/log4sp/utils-inl.h index 3bd2466..2f6c4c1 100644 --- a/src/log4sp/utils-inl.h +++ b/src/log4sp/utils-inl.h @@ -1,12 +1,12 @@ #ifndef _LOG4SP_UTILS_INL_H_ #define _LOG4SP_UTILS_INL_H_ -#include +#include "log4sp/utils.h" namespace log4sp { -inline spdlog::level::level_enum cell_to_level(cell_t lvl) +inline spdlog::level::level_enum cell_to_level(cell_t lvl) noexcept { if (lvl < 0) { @@ -21,7 +21,7 @@ inline spdlog::level::level_enum cell_to_level(cell_t lvl) return static_cast(lvl); } -inline spdlog::async_overflow_policy cell_to_policy(cell_t policy) +inline spdlog::async_overflow_policy cell_to_policy(cell_t policy) noexcept { if (policy < 0) { @@ -36,7 +36,7 @@ inline spdlog::async_overflow_policy cell_to_policy(cell_t policy) return static_cast(policy); } -inline spdlog::pattern_time_type cell_to_pattern_time_type(cell_t type) +inline spdlog::pattern_time_type cell_to_pattern_time_type(cell_t type) noexcept { if (type < 0) { @@ -133,7 +133,7 @@ inline std::string format_cell_to_string(SourcePawn::IPluginContext *ctx, const #define ZEROPAD 0x00000002 /* zero (as opposed to blank) pad */ #define UPPERDIGITS 0x00000004 /* make alpha digits uppercase */ -inline void ReorderTranslationParams(const Translation *pTrans, cell_t *params) +inline static void ReorderTranslationParams(const Translation *pTrans, cell_t *params) { cell_t new_params[MAX_TRANSLATE_PARAMS]; for (unsigned int i = 0; i < pTrans->fmt_count; i++) @@ -143,7 +143,7 @@ inline void ReorderTranslationParams(const Translation *pTrans, cell_t *params) memcpy(params, new_params, pTrans->fmt_count * sizeof(cell_t)); } -inline fmt::memory_buffer Translate(IPluginContext *ctx, const char *key, cell_t target, const cell_t *params, int *arg) +inline static fmt::memory_buffer Translate(IPluginContext *ctx, const char *key, cell_t target, const cell_t *params, int *arg) { unsigned int langid; Translation pTrans; @@ -223,31 +223,25 @@ inline fmt::memory_buffer Translate(IPluginContext *ctx, const char *key, cell_t } } -inline bool AddString(fmt::memory_buffer &out, const char *string, int width, int prec) +inline static void AddString(fmt::memory_buffer &out, const char *string, int width, int prec) { - int size = 0; - static char nlstr[] = {'(','n','u','l','l',')','\0'}; + const char nlstr[] = {'(','n','u','l','l',')','\0'}; - if (string == NULL) + if (string == nullptr) { string = nlstr; prec = -1; } + int size = 0; if (prec >= 0) { - for (size = 0; size < prec; ++size) - { - if (string[size] == '\0') - { - break; - } - } + while (string[size] && (prec > size++)) ; } else { - while (string[size++]); - size--; + while (string[size++]) ; + --size; } width -= size; @@ -261,11 +255,9 @@ inline bool AddString(fmt::memory_buffer &out, const char *string, int width, in { out.push_back(' '); } - - return true; } -inline void AddFloat(fmt::memory_buffer &out, double fval, int width, int prec, int flags) +inline static void AddFloat(fmt::memory_buffer &out, double fval, int width, int prec, int flags) { int digits; // non-fraction part digits double tmp; // temporary @@ -317,18 +309,16 @@ inline void AddFloat(fmt::memory_buffer &out, double fval, int width, int prec, { if (flags & ZEROPAD) { - while ((fieldlength < width)) + while (fieldlength < width--) { out.push_back('0'); - width--; } } else { - while ((fieldlength < width)) + while (fieldlength < width--) { out.push_back(' '); - width--; } } } @@ -343,14 +333,14 @@ inline void AddFloat(fmt::memory_buffer &out, double fval, int width, int prec, tmp = std::pow(10.0, digits - 1); if (++significant_digits > MAX_SIGNIFICANT_DIGITS) { - while ((digits--)) + while (digits--) { out.push_back('0'); } } else { - while ((digits--)) + while (digits--) { val = (int)(fval / tmp); out.push_back('0' + val); @@ -389,26 +379,23 @@ inline void AddFloat(fmt::memory_buffer &out, double fval, int width, int prec, // left justify if required if (flags & LADJUST) { - while ((fieldlength < width)) + while (fieldlength < width--) { // right-padding only with spaces, ZEROPAD is ignored out.push_back(' '); - width--; } } } -inline void AddBinary(fmt::memory_buffer &out, unsigned int val, int width, int flags) +inline static void AddBinary(fmt::memory_buffer &out, unsigned int val, int width, int flags) { - char text[32]; - int digits; - - digits = 0; - do + int digits = 32; + unsigned int offset = 1 << 31; + while ((val & offset) == 0) { - text[digits++] = (val & 1) ? '1' : '0'; - val >>= 1; - } while (val); + --digits; + offset >>= 1; + } if (!(flags & LADJUST)) { @@ -417,7 +404,7 @@ inline void AddBinary(fmt::memory_buffer &out, unsigned int val, int width, int while (digits < width) { out.push_back('0'); - width--; + --width; } } else @@ -425,7 +412,7 @@ inline void AddBinary(fmt::memory_buffer &out, unsigned int val, int width, int while (digits < width) { out.push_back(' '); - width--; + --width; } } } @@ -433,7 +420,8 @@ inline void AddBinary(fmt::memory_buffer &out, unsigned int val, int width, int width -= digits; while (digits--) { - out.push_back(text[digits]); + out.push_back(val & offset ? '1' : '0'); + offset >>= 1; } if (flags & LADJUST) @@ -455,34 +443,29 @@ inline void AddBinary(fmt::memory_buffer &out, unsigned int val, int width, int } } -inline void AddUInt(fmt::memory_buffer &out, unsigned int val, int width, int flags) +inline static void AddUInt(fmt::memory_buffer &out, unsigned int val, int width, int flags) { - char text[32]; - int digits; - - digits = 0; + char text[10]; + int digits = 0; do { text[digits++] = '0' + val % 10; - val /= 10; - } while (val); + } while (val /= 10); if (!(flags & LADJUST)) { if (flags & ZEROPAD) { - while (digits < width) + while (digits < width--) { out.push_back('0'); - width--; } } else { - while ((digits < width)) + while (digits < width--) { out.push_back(' '); - width--; } } } @@ -512,55 +495,48 @@ inline void AddUInt(fmt::memory_buffer &out, unsigned int val, int width, int fl } } -inline void AddInt(fmt::memory_buffer &out, int val, int width, int flags) +inline static void AddInt(fmt::memory_buffer &out, int val, int width, int flags) { - char text[32]; - int digits; - int signedVal; - unsigned int unsignedVal; + char text[10]; + int digits = 0; - digits = 0; - signedVal = val; - if (val < 0) - { - /* we want the unsigned version */ - unsignedVal = abs(val); - } - else - { - unsignedVal = val; - } + bool negative = val < 0; + unsigned int unsignedVal = negative ? abs(val) : val; do { text[digits++] = '0' + unsignedVal % 10; - unsignedVal /= 10; - } while (unsignedVal); - - if (signedVal < 0) - { - text[digits++] = '-'; - } + } while (unsignedVal /= 10); if (!(flags & LADJUST)) { if (flags & ZEROPAD) { - while ((digits < width)) + if (negative) + { + out.push_back('-'); + } + while (digits < width--) { out.push_back('0'); - width--; } } else { - while ((digits < width)) + while (digits < width--) { out.push_back(' '); - width--; + } + if (negative) + { + out.push_back('-'); } } } + else if (negative) + { + out.push_back('-'); + } width -= digits; while (digits--) @@ -587,22 +563,27 @@ inline void AddInt(fmt::memory_buffer &out, int val, int width, int flags) } } -inline void AddHex(fmt::memory_buffer &out, unsigned int val, int width, int flags) +inline static void AddHex(fmt::memory_buffer &out, unsigned int val, int width, int flags) { - static char hexAdjustUppercase[] = "0123456789ABCDEF"; - static char hexAdjustLowercase[] = "0123456789abcdef"; - char text[32]; - int digits; - const char *hexadjust; + char text[8]; + int digits = 0; - hexadjust = (flags & UPPERDIGITS) ? hexAdjustUppercase : hexAdjustLowercase; - - digits = 0; - do + if (flags & UPPERDIGITS) { - text[digits++] = hexadjust[val % 16]; - val /= 16; - } while(val); + const char hexAdjust[] = "0123456789ABCDEF"; + do + { + text[digits++] = hexAdjust[val & 0xF]; + } while(val >>= 4); + } + else + { + const char hexAdjust[] = "0123456789abcdef"; + do + { + text[digits++] = hexAdjust[val & 0xF]; + } while(val >>= 4); + } if (!(flags & LADJUST)) { @@ -611,7 +592,7 @@ inline void AddHex(fmt::memory_buffer &out, unsigned int val, int width, int fla while (digits < width) { out.push_back('0'); - width--; + --width; } } else @@ -619,7 +600,7 @@ inline void AddHex(fmt::memory_buffer &out, unsigned int val, int width, int fla while (digits < width) { out.push_back(' '); - width--; + --width; } } } @@ -649,20 +630,30 @@ inline void AddHex(fmt::memory_buffer &out, unsigned int val, int width, int fla } } -inline bool DescribePlayer(int index, const char **namep, const char **authp, int *useridp) +inline static bool DescribePlayer(int index, const char **namep, const char **authp, int *useridp) { auto player = playerhelpers->GetGamePlayer(index); if (!player || !player->IsConnected()) + { return false; + } - if (namep) + if (namep != nullptr) + { *namep = player->GetName(); - if (authp) { + } + + if (authp != nullptr) + { const char *auth = player->GetAuthString(); *authp = (auth && *auth) ? auth : "STEAM_ID_PENDING"; } - if (useridp) + + if (useridp != nullptr) + { *useridp = player->GetUserId(); + } + return true; } @@ -713,16 +704,14 @@ inline fmt::memory_buffer format_cell_to_memory_buf(const char *format, SourcePa flags |= LADJUST; goto rflag; } - case '!': - { - goto rflag; - } case '.': { n = 0; - while(std::isdigit((ch = *fmt++))) + ch = *fmt++; + while (ch >= '0' && ch <= '9') { n = 10 * n + (ch - '0'); + ch = *fmt++; } prec = (n < 0) ? -1 : n; goto reswitch; @@ -747,7 +736,7 @@ inline fmt::memory_buffer format_cell_to_memory_buf(const char *format, SourcePa { n = 10 * n + (ch - '0'); ch = *fmt++; - } while(std::isdigit(ch)); + } while(ch >= '0' && ch <= '9'); width = n; goto reswitch; } diff --git a/src/log4sp/utils.h b/src/log4sp/utils.h index a4b6ce2..976826c 100644 --- a/src/log4sp/utils.h +++ b/src/log4sp/utils.h @@ -13,19 +13,19 @@ namespace log4sp { * 将 cell_t 转为 spdlog::level::level_enum * 如果 cell_t 越界,则返回最近的边界值 */ -spdlog::level::level_enum cell_to_level(cell_t lvl); +spdlog::level::level_enum cell_to_level(cell_t lvl) noexcept; /** * 将 cell_t 转为 spdlog::async_overflow_policy * 如果 cell_t 越界,则返回最近的边界值 */ -spdlog::async_overflow_policy cell_to_policy(cell_t policy); +spdlog::async_overflow_policy cell_to_policy(cell_t policy) noexcept; /** * 将 cell_t 转为 spdlog::pattern_time_type * 如果 cell_t 越界,则返回最近的边界值 */ -spdlog::pattern_time_type cell_to_pattern_time_type(cell_t type); +spdlog::pattern_time_type cell_to_pattern_time_type(cell_t type) noexcept; /** * 获取插件调用 native 的源代码位置 diff --git a/src/natives/common.cpp b/src/natives/common.cpp index 396addd..0d2fde1 100644 --- a/src/natives/common.cpp +++ b/src/natives/common.cpp @@ -1,4 +1,4 @@ -#include +#include "log4sp/utils.h" /** * native void LogLevelToName(LogLevel lvl, char[] buffer, int maxlen); @@ -62,5 +62,5 @@ const sp_nativeinfo_t CommonNatives[] = {"LogLevelToName", LogLevelToName}, {"LogLevelToShortName", LogLevelToShortName}, {"NameToLogLevel", NameToLogLevel}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/logger.cpp b/src/natives/logger.cpp index 4227bb2..49024cb 100644 --- a/src/natives/logger.cpp +++ b/src/natives/logger.cpp @@ -6,22 +6,13 @@ #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/daily_file_sink.h" -#include -#include -#include +#include "log4sp/utils.h" +#include "log4sp/sink_register.h" +#include "log4sp/logger_register.h" +#include "log4sp/adapter/base_sink.h" +#include "log4sp/adapter/sync_logger.h" +#include "log4sp/adapter/async_logger.h" -/** - * Thread safe logger (except for set_error_handler()) - * Has name, log level, vector of std::shared sink pointers and formatter - * Upon each log write the logger: - * 1. Checks if its log level is enough to log the message and if yes: - * 2. Call the underlying sinks to do the job. - * 3. Each sink use its own private copy of a formatter to format the message - * and send to its destination. - * - * The use of private formatter per sink provides the opportunity to cache some - * formatted data, and support for different format per sink. - */ /** * public native Logger(const char[] name, Sink[] sinks, int numSinks, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block); @@ -30,13 +21,7 @@ static cell_t Logger(IPluginContext *ctx, const cell_t *params) { char *name; ctx->LocalToString(params[1], &name); - if (!strcmp(name, SMEXT_CONF_LOGTAG)) - { - ctx->ReportError("'" SMEXT_CONF_LOGTAG "' is a reserved dedicated logger name."); - return BAD_HANDLE; - } - - if (log4sp::logger_handle_manager::instance().get_data(name) != nullptr) + if (log4sp::logger_register::instance().get(name) != nullptr) { ctx->ReportError("Logger with name '%s' already exists.", name); return BAD_HANDLE; @@ -46,43 +31,44 @@ static cell_t Logger(IPluginContext *ctx, const cell_t *params) ctx->LocalToPhysAddr(params[2], &sinks); auto numSinks = static_cast(params[3]); - auto async = static_cast(params[4]); std::vector sinksList; + sinksList.reserve(numSinks); + for (unsigned int i = 0; i < numSinks; ++i) { - auto sinkHandle = static_cast(sinks[i]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, sinkHandle); - if (sink == nullptr) + auto sinkHandle = static_cast(sinks[i]); + auto sinkAdapterRaw = log4sp::base_sink::read(sinkHandle, ctx); + if (sinkAdapterRaw == nullptr) { return BAD_HANDLE; } - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - if (data == nullptr) - { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(sinkHandle)); - return BAD_HANDLE; - } + sinksList.push_back(sinkAdapterRaw->raw()); + } - if (data->is_multi_threaded() != async) - { - ctx->ReportError("You cannot create a %s logger with a %s sink.", async ? "asynchronous" : "synchronous", async ? "synchronous" : "asynchronous"); - return BAD_HANDLE; - } + std::shared_ptr loggerAdapter; - sinksList.push_back(data->sink_ptr()); + auto async = static_cast(params[4]); + if (!async) + { + auto logger = std::make_shared(name, sinksList.begin(), sinksList.end()); + loggerAdapter = log4sp::sync_logger::create(logger, ctx); + } + else + { + auto policy = log4sp::cell_to_policy(params[5]); + auto distSink = std::make_shared(sinksList); + auto logger = std::make_shared(name, distSink, spdlog::thread_pool(), policy); + loggerAdapter = log4sp::async_logger::create(logger, ctx); } - if (!async) + if (loggerAdapter == nullptr) { - auto data = log4sp::logger_handle_manager::instance().create_logger_st(ctx, name, sinksList); - return data->handle(); + return BAD_HANDLE; } - auto policy = log4sp::cell_to_policy(params[5]); - auto data = log4sp::logger_handle_manager::instance().create_logger_mt(ctx, name, sinksList, policy); - return data->handle(); + return loggerAdapter->handle(); } /** @@ -92,51 +78,50 @@ static cell_t Get(IPluginContext *ctx, const cell_t *params) { char *name; ctx->LocalToString(params[1], &name); - if (!strcmp(name, SMEXT_CONF_LOGTAG)) - { - ctx->ReportError("The logger named '" SMEXT_CONF_LOGTAG "' is reserved dedicated logger."); - return BAD_HANDLE; - } - - auto data = log4sp::logger_handle_manager::instance().get_data(name); - if (data == nullptr) - { - ctx->ReportError("Logger named '%s' does not exist.", name); - return BAD_HANDLE; - } - return data->handle(); + auto loggerAdapter = log4sp::logger_register::instance().get(name); + return loggerAdapter == nullptr ? BAD_HANDLE : loggerAdapter->handle(); } /** - * public static native Logger CreateServerConsoleLogger(const char[] name, bool async = false, AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block); + * public static native Logger CreateServerConsoleLogger(const char[] name, + * bool async = false, + * AsyncOverflowPolicy policy = AsyncOverflowPolicy_Block); */ static cell_t CreateServerConsoleLogger(IPluginContext *ctx, const cell_t *params) { char *name; ctx->LocalToString(params[1], &name); - if (!strcmp(name, SMEXT_CONF_LOGTAG)) - { - ctx->ReportError("'" SMEXT_CONF_LOGTAG "' is a reserved dedicated logger name."); - return BAD_HANDLE; - } - - if (log4sp::logger_handle_manager::instance().get_data(name) != nullptr) + if (log4sp::logger_register::instance().get(name) != nullptr) { ctx->ReportError("Logger with name '%s' already exists.", name); return BAD_HANDLE; } + std::shared_ptr loggerAdapter; + auto async = static_cast(params[2]); if (!async) { - auto data = log4sp::logger_handle_manager::instance().create_server_console_logger_st(ctx, name); - return data->handle(); + auto sink = std::make_shared(); + auto logger = std::make_shared(name, sink); + loggerAdapter = log4sp::sync_logger::create(logger, ctx); + } + else + { + auto policy = log4sp::cell_to_policy(params[3]); + auto sink = std::make_shared(); + auto distSink = std::make_shared(std::vector {sink}); + auto logger = std::make_shared(name, distSink, spdlog::thread_pool(), policy); + loggerAdapter = log4sp::async_logger::create(logger, ctx); + } + + if (loggerAdapter == nullptr) + { + return BAD_HANDLE; } - auto policy = log4sp::cell_to_policy(params[3]); - auto data = log4sp::logger_handle_manager::instance().create_server_console_logger_mt(ctx, name, policy); - return data->handle(); + return loggerAdapter->handle(); } /** @@ -151,13 +136,7 @@ static cell_t CreateBaseFileLogger(IPluginContext *ctx, const cell_t *params) { char *name; ctx->LocalToString(params[1], &name); - if (!strcmp(name, SMEXT_CONF_LOGTAG)) - { - ctx->ReportError("'" SMEXT_CONF_LOGTAG "' is a reserved dedicated logger name."); - return BAD_HANDLE; - } - - if (log4sp::logger_handle_manager::instance().get_data(name) != nullptr) + if (log4sp::logger_register::instance().get(name) != nullptr) { ctx->ReportError("Logger with name '%s' already exists.", name); return BAD_HANDLE; @@ -165,20 +144,35 @@ static cell_t CreateBaseFileLogger(IPluginContext *ctx, const cell_t *params) char *file; ctx->LocalToString(params[2], &file); + char path[PLATFORM_MAX_PATH]; smutils->BuildPath(Path_Game, path, sizeof(path), "%s", file); + std::shared_ptr loggerAdapter; + auto truncate = static_cast(params[3]); - auto async = static_cast(params[4]); + auto async = static_cast(params[4]); if (!async) { - auto data = log4sp::logger_handle_manager::instance().create_base_file_logger_st(ctx, name, path, truncate); - return data->handle(); + auto sink = std::make_shared(path, truncate); + auto logger = std::make_shared(name, sink); + loggerAdapter = log4sp::sync_logger::create(logger, ctx); + } + else + { + auto policy = log4sp::cell_to_policy(params[5]); + auto sink = std::make_shared(path, truncate); + auto distSink = std::make_shared(std::vector {sink}); + auto logger = std::make_shared(name, distSink, spdlog::thread_pool(), policy); + loggerAdapter = log4sp::async_logger::create(logger, ctx); + } + + if (loggerAdapter == nullptr) + { + return BAD_HANDLE; } - auto policy = log4sp::cell_to_policy(params[5]); - auto data = log4sp::logger_handle_manager::instance().create_base_file_logger_mt(ctx, name, path, truncate, policy); - return data->handle(); + return loggerAdapter->handle(); } /** @@ -195,13 +189,7 @@ static cell_t CreateRotatingFileLogger(IPluginContext *ctx, const cell_t *params { char *name; ctx->LocalToString(params[1], &name); - if (!strcmp(name, SMEXT_CONF_LOGTAG)) - { - ctx->ReportError("'" SMEXT_CONF_LOGTAG "' is a reserved dedicated logger name."); - return BAD_HANDLE; - } - - if (log4sp::logger_handle_manager::instance().get_data(name) != nullptr) + if (log4sp::logger_register::instance().get(name) != nullptr) { ctx->ReportError("Logger with name '%s' already exists.", name); return BAD_HANDLE; @@ -209,6 +197,7 @@ static cell_t CreateRotatingFileLogger(IPluginContext *ctx, const cell_t *params char *file; ctx->LocalToString(params[2], &file); + char path[PLATFORM_MAX_PATH]; smutils->BuildPath(Path_Game, path, sizeof(path), "%s", file); @@ -226,17 +215,31 @@ static cell_t CreateRotatingFileLogger(IPluginContext *ctx, const cell_t *params return BAD_HANDLE; } + std::shared_ptr loggerAdapter; + auto rotateOnOpen = static_cast(params[5]); - auto async = static_cast(params[6]); + auto async = static_cast(params[6]); if (!async) { - auto data = log4sp::logger_handle_manager::instance().create_rotating_file_logger_st(ctx, name, path, maxFileSize, maxFiles, rotateOnOpen); - return data->handle(); + auto sink = std::make_shared(path, maxFileSize, maxFiles, rotateOnOpen); + auto logger = std::make_shared(name, sink); + loggerAdapter = log4sp::sync_logger::create(logger, ctx); + } + else + { + auto policy = log4sp::cell_to_policy(params[7]); + auto sink = std::make_shared(path, maxFileSize, maxFiles, rotateOnOpen); + auto distSink = std::make_shared(std::vector {sink}); + auto logger = std::make_shared(name, distSink, spdlog::thread_pool(), policy); + loggerAdapter = log4sp::async_logger::create(logger, ctx); } - auto policy = log4sp::cell_to_policy(params[7]); - auto data = log4sp::logger_handle_manager::instance().create_rotating_file_logger_mt(ctx, name, path, maxFileSize, maxFiles, rotateOnOpen, policy); - return data->handle(); + if (loggerAdapter == nullptr) + { + return BAD_HANDLE; + } + + return loggerAdapter->handle(); } /** @@ -254,13 +257,7 @@ static cell_t CreateDailyFileLogger(IPluginContext *ctx, const cell_t *params) { char *name; ctx->LocalToString(params[1], &name); - if (!strcmp(name, SMEXT_CONF_LOGTAG)) - { - ctx->ReportError("'" SMEXT_CONF_LOGTAG "' is a reserved dedicated logger name."); - return BAD_HANDLE; - } - - if (log4sp::logger_handle_manager::instance().get_data(name) != nullptr) + if (log4sp::logger_register::instance().get(name) != nullptr) { ctx->ReportError("Logger with name '%s' already exists.", name); return BAD_HANDLE; @@ -268,10 +265,11 @@ static cell_t CreateDailyFileLogger(IPluginContext *ctx, const cell_t *params) char *file; ctx->LocalToString(params[2], &file); + char path[PLATFORM_MAX_PATH]; smutils->BuildPath(Path_Game, path, sizeof(path), "%s", file); - auto hour = static_cast(params[3]); + auto hour = static_cast(params[3]); auto minute = static_cast(params[4]); if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { @@ -279,18 +277,32 @@ static cell_t CreateDailyFileLogger(IPluginContext *ctx, const cell_t *params) return BAD_HANDLE; } + std::shared_ptr loggerAdapter; + auto truncate = static_cast(params[5]); auto maxFiles = static_cast(params[6]); - auto async = static_cast(params[7]); + auto async = static_cast(params[7]); if (!async) { - auto data = log4sp::logger_handle_manager::instance().create_daily_file_logger_st(ctx, name, path, hour, minute, truncate, maxFiles); - return data->handle(); + auto sink = std::make_shared(path, hour, minute, truncate, maxFiles); + auto logger = std::make_shared(name, sink); + loggerAdapter = log4sp::sync_logger::create(logger, ctx); + } + else + { + auto policy = log4sp::cell_to_policy(params[8]); + auto sink = std::make_shared(path, hour, minute, truncate, maxFiles); + auto distSink = std::make_shared(std::vector {sink}); + auto logger = std::make_shared(name, distSink, spdlog::thread_pool(), policy); + loggerAdapter = log4sp::async_logger::create(logger, ctx); + } + + if (loggerAdapter == nullptr) + { + return BAD_HANDLE; } - auto policy = log4sp::cell_to_policy(params[8]); - auto data = log4sp::logger_handle_manager::instance().create_daily_file_logger_mt(ctx, name, path, hour, minute, truncate, maxFiles, policy); - return data->handle(); + return loggerAdapter->handle(); } /** @@ -299,13 +311,13 @@ static cell_t CreateDailyFileLogger(IPluginContext *ctx, const cell_t *params) static cell_t GetName(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - ctx->StringToLocal(params[2], params[3], logger->name().c_str()); + ctx->StringToLocal(params[2], params[3], logger->raw()->name().c_str()); return 0; } @@ -315,13 +327,13 @@ static cell_t GetName(IPluginContext *ctx, const cell_t *params) static cell_t GetLevel(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - return logger->level(); + return static_cast(logger->raw()->level()); } /** @@ -330,7 +342,7 @@ static cell_t GetLevel(IPluginContext *ctx, const cell_t *params) static cell_t SetLevel(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -338,28 +350,17 @@ static cell_t SetLevel(IPluginContext *ctx, const cell_t *params) auto lvl = log4sp::cell_to_level(params[2]); - logger->set_level(lvl); + logger->raw()->set_level(lvl); return 0; } -/** - * set formatting for the sinks in this logger. - * each sink will get a separate instance of the formatter object. - * - * set formatting for the sinks in this logger. - * equivalent to - * set_formatter(make_unique(pattern, time_type)) - * Note: each sink will get a new instance of a formatter object, replacing the old one. - * - * pattern flags (https://github.com/gabime/spdlog/wiki/3.-Custom-formatting#pattern-flags) - */ /** * public native void SetPattern(const char[] pattern, PatternTimeType type = PatternTimeType_local); */ static cell_t SetPattern(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -370,7 +371,7 @@ static cell_t SetPattern(IPluginContext *ctx, const cell_t *params) auto type = log4sp::cell_to_pattern_time_type(params[3]); - logger->set_pattern(pattern, type); + logger->raw()->set_pattern(pattern, type); return 0; } @@ -380,7 +381,7 @@ static cell_t SetPattern(IPluginContext *ctx, const cell_t *params) static cell_t ShouldLog(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -388,7 +389,7 @@ static cell_t ShouldLog(IPluginContext *ctx, const cell_t *params) auto lvl = log4sp::cell_to_level(params[2]); - return logger->should_log(lvl); + return logger->raw()->should_log(lvl); } /** @@ -397,7 +398,7 @@ static cell_t ShouldLog(IPluginContext *ctx, const cell_t *params) static cell_t Log(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -408,7 +409,7 @@ static cell_t Log(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[3], &msg); - logger->log(lvl, msg); + logger->raw()->log(lvl, msg); return 0; } @@ -418,14 +419,12 @@ static cell_t Log(IPluginContext *ctx, const cell_t *params) static cell_t LogEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - auto lvl = log4sp::cell_to_level(params[2]); - std::string msg; try { @@ -433,13 +432,39 @@ static cell_t LogEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); return 0; } - logger->log(lvl, msg); + auto lvl = log4sp::cell_to_level(params[2]); + + logger->raw()->log(lvl, msg); + return 0; +} + +/** + * public native void LogAmxTpl(LogLevel lvl, const char[] fmt, any ...); + */ +static cell_t LogAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 3); + if (eh.HasException()) + { + return 0; + } + + auto lvl = log4sp::cell_to_level(params[2]); + + logger->raw()->log(lvl, msg); return 0; } @@ -449,19 +474,19 @@ static cell_t LogEx(IPluginContext *ctx, const cell_t *params) static cell_t LogSrc(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } auto lvl = log4sp::cell_to_level(params[2]); + auto loc = log4sp::get_plugin_source_loc(ctx); char *msg; ctx->LocalToString(params[3], &msg); - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, lvl, msg); + logger->raw()->log(loc, lvl, msg); return 0; } @@ -471,29 +496,54 @@ static cell_t LogSrc(IPluginContext *ctx, const cell_t *params) static cell_t LogSrcEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - auto lvl = log4sp::cell_to_level(params[2]); - std::string msg; - auto loc = log4sp::get_plugin_source_loc(ctx); - try { msg = log4sp::format_cell_to_string(ctx, params, 3); } catch(const std::exception& e) { - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); + return 0; + } + + auto lvl = log4sp::cell_to_level(params[2]); + auto loc = log4sp::get_plugin_source_loc(ctx); + + logger->raw()->log(loc, lvl, msg); + return 0; +} + +/** + * public native void LogSrcAmxTpl(LogLevel lvl, const char[] fmt, any ...); + */ +static cell_t LogSrcAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { return 0; } - logger->log(loc, lvl, msg); + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 3); + if (eh.HasException()) + { + return 0; + } + + auto lvl = log4sp::cell_to_level(params[2]); + auto loc = log4sp::get_plugin_source_loc(ctx); + + logger->raw()->log(loc, lvl, msg); return 0; } @@ -503,7 +553,7 @@ static cell_t LogSrcEx(IPluginContext *ctx, const cell_t *params) static cell_t LogLoc(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -512,18 +562,17 @@ static cell_t LogLoc(IPluginContext *ctx, const cell_t *params) char *file; ctx->LocalToString(params[2], &file); - auto line = static_cast(params[3]); - char *func; ctx->LocalToString(params[4], &func); - auto lvl = log4sp::cell_to_level(params[5]); - char *msg; ctx->LocalToString(params[6], &msg); - auto loc = spdlog::source_loc{file, line, func}; - logger->log(loc, lvl, msg); + auto line = static_cast(params[3]); + auto lvl = log4sp::cell_to_level(params[5]); + auto loc = spdlog::source_loc {file, line, func}; + + logger->raw()->log(loc, lvl, msg); return 0; } @@ -533,37 +582,68 @@ static cell_t LogLoc(IPluginContext *ctx, const cell_t *params) static cell_t LogLocEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } + std::string msg; + try + { + msg = log4sp::format_cell_to_string(ctx, params, 6); + } + catch(const std::exception& e) + { + logger->error_handler(e.what()); + return 0; + } + char *file; ctx->LocalToString(params[2], &file); - auto line = static_cast(params[3]); - char *func; ctx->LocalToString(params[4], &func); - auto lvl = log4sp::cell_to_level(params[5]); + auto line = static_cast(params[3]); + auto lvl = log4sp::cell_to_level(params[5]); + auto loc = spdlog::source_loc {file, line, func}; - std::string msg; - try + logger->raw()->log(loc, lvl, msg); + return 0; +} + +/** + * public native void LogLocAmxTpl(const char[] file, int line, const char[] func, LogLevel lvl, const char[] fmt, any ...); + */ +static cell_t LogLocAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) { - msg = log4sp::format_cell_to_string(ctx, params, 6); + return 0; } - catch(const std::exception& e) + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 6); + if (eh.HasException()) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); return 0; } - auto loc = spdlog::source_loc{file, line, func}; - logger->log(loc, lvl, msg); + char *file; + ctx->LocalToString(params[2], &file); + + char *func; + ctx->LocalToString(params[4], &func); + + auto line = static_cast(params[3]); + auto lvl = log4sp::cell_to_level(params[5]); + auto loc = spdlog::source_loc {file, line, func}; + + logger->raw()->log(loc, lvl, msg); return 0; } @@ -573,7 +653,7 @@ static cell_t LogLocEx(IPluginContext *ctx, const cell_t *params) static cell_t LogStackTrace(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -583,15 +663,15 @@ static cell_t LogStackTrace(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[3], &msg); - logger->log(lvl, "Stack trace requested: {}", msg); + logger->raw()->log(lvl, "Stack trace requested: {}", msg); - auto plugin = plsys->FindPluginByContext(ctx->GetContext()); - logger->log(lvl, "Called from: {}", plugin->GetFilename()); + auto plugin = plsys->FindPluginByContext(ctx->GetContext())->GetFilename(); + logger->raw()->log(lvl, "Called from: {}", plugin); - auto arr = log4sp::get_stack_trace(ctx); - for (size_t i = 0; i < arr.size(); ++i) + auto stackTrace = log4sp::get_stack_trace(ctx); + for (auto iter : stackTrace) { - logger->log(lvl, arr[i].c_str()); + logger->raw()->log(lvl, iter.c_str()); } return 0; } @@ -602,14 +682,12 @@ static cell_t LogStackTrace(IPluginContext *ctx, const cell_t *params) static cell_t LogStackTraceEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - auto lvl = log4sp::cell_to_level(params[2]); - std::string msg; try { @@ -617,21 +695,54 @@ static cell_t LogStackTraceEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); return 0; } - logger->log(lvl, "Stack trace requested: {}", msg); + auto lvl = log4sp::cell_to_level(params[2]); + logger->raw()->log(lvl, "Stack trace requested: {}", msg); - auto plugin = plsys->FindPluginByContext(ctx->GetContext()); - logger->log(lvl, "Called from: {}", plugin->GetFilename()); + auto plugin = plsys->FindPluginByContext(ctx->GetContext())->GetFilename(); + logger->raw()->log(lvl, "Called from: {}", plugin); - auto arr = log4sp::get_stack_trace(ctx); - for (size_t i = 0; i < arr.size(); ++i) + auto stackTrace = log4sp::get_stack_trace(ctx); + for (auto iter : stackTrace) { - logger->log(lvl, arr[i].c_str()); + logger->raw()->log(lvl, iter.c_str()); + } + return 0; +} + +/** + * public native void LogStackTraceAmxTpl(LogLevel lvl, const char[] msg, any ...); + */ +static cell_t LogStackTraceAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 3); + if (eh.HasException()) + { + return 0; + } + + auto lvl = log4sp::cell_to_level(params[2]); + logger->raw()->log(lvl, "Stack trace requested: {}", msg); + + auto plugin = plsys->FindPluginByContext(ctx->GetContext())->GetFilename(); + logger->raw()->log(lvl, "Called from: {}", plugin); + + auto stackTrace = log4sp::get_stack_trace(ctx); + for (auto iter : stackTrace) + { + logger->raw()->log(lvl, iter.c_str()); } return 0; } @@ -642,7 +753,7 @@ static cell_t LogStackTraceEx(IPluginContext *ctx, const cell_t *params) static cell_t ThrowError(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -652,15 +763,15 @@ static cell_t ThrowError(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[3], &msg); - logger->log(lvl, "Exception reported: {}", msg); + logger->raw()->log(lvl, "Exception reported: {}", msg); - auto plugin = plsys->FindPluginByContext(ctx->GetContext()); - logger->log(lvl, "Blaming: {}", plugin->GetFilename()); + auto plugin = plsys->FindPluginByContext(ctx->GetContext())->GetFilename(); + logger->raw()->log(lvl, "Blaming: {}", plugin); - auto arr = log4sp::get_stack_trace(ctx); - for (size_t i = 0; i < arr.size(); ++i) + auto stackTrace = log4sp::get_stack_trace(ctx); + for (auto iter : stackTrace) { - logger->log(lvl, arr[i].c_str()); + logger->raw()->log(lvl, iter.c_str()); } ctx->ReportError(msg); @@ -673,14 +784,12 @@ static cell_t ThrowError(IPluginContext *ctx, const cell_t *params) static cell_t ThrowErrorEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - auto lvl = log4sp::cell_to_level(params[2]); - std::string msg; try { @@ -688,35 +797,70 @@ static cell_t ThrowErrorEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); ctx->ReportError(e.what()); return 0; } - logger->log(lvl, "Exception reported: {}", msg); + auto lvl = log4sp::cell_to_level(params[2]); + logger->raw()->log(lvl, "Exception reported: {}", msg); - auto plugin = plsys->FindPluginByContext(ctx->GetContext()); - logger->log(lvl, "Blaming: {}", plugin->GetFilename()); + auto plugin = plsys->FindPluginByContext(ctx->GetContext())->GetFilename(); + logger->raw()->log(lvl, "Blaming: {}", plugin); - auto arr = log4sp::get_stack_trace(ctx); - for (size_t i = 0; i < arr.size(); ++i) + auto stackTrace = log4sp::get_stack_trace(ctx); + for (auto iter : stackTrace) { - logger->log(lvl, arr[i].c_str()); + logger->raw()->log(lvl, iter.c_str()); } ctx->ReportError(msg.c_str()); return 0; } +/** + * public native void ThrowErrorAmxTpl(LogLevel lvl, const char[] msg, any ...); + */ +static cell_t ThrowErrorAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 3); + if (eh.HasException()) + { + return 0; + } + + auto lvl = log4sp::cell_to_level(params[2]); + logger->raw()->log(lvl, "Exception reported: {}", msg); + + auto plugin = plsys->FindPluginByContext(ctx->GetContext())->GetFilename(); + logger->raw()->log(lvl, "Blaming: {}", plugin); + + auto stackTrace = log4sp::get_stack_trace(ctx); + for (auto iter : stackTrace) + { + logger->raw()->log(lvl, iter.c_str()); + } + + ctx->ReportError(msg); + return 0; +} + /** * public native void Trace(const char[] msg); */ static cell_t Trace(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -725,7 +869,7 @@ static cell_t Trace(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[2], &msg); - logger->trace(msg); + logger->raw()->trace(msg); return 0; } @@ -735,7 +879,7 @@ static cell_t Trace(IPluginContext *ctx, const cell_t *params) static cell_t TraceEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -748,13 +892,35 @@ static cell_t TraceEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); + return 0; + } + + logger->raw()->trace(msg); + return 0; +} + +/** + * public native void TraceAmxTpl(const char[] fmt, any ...); + */ +static cell_t TraceAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 2); + if (eh.HasException()) + { return 0; } - logger->trace(msg); + logger->raw()->trace(msg); return 0; } @@ -764,7 +930,7 @@ static cell_t TraceEx(IPluginContext *ctx, const cell_t *params) static cell_t Debug(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -773,7 +939,7 @@ static cell_t Debug(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[2], &msg); - logger->debug(msg); + logger->raw()->debug(msg); return 0; } @@ -783,7 +949,7 @@ static cell_t Debug(IPluginContext *ctx, const cell_t *params) static cell_t DebugEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -796,13 +962,35 @@ static cell_t DebugEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); + return 0; + } + + logger->raw()->debug(msg); + return 0; +} + +/** + * public native void DebugAmxTpl(const char[] fmt, any ...); + */ +static cell_t DebugAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 2); + if (eh.HasException()) + { return 0; } - logger->debug(msg); + logger->raw()->debug(msg); return 0; } @@ -812,7 +1000,7 @@ static cell_t DebugEx(IPluginContext *ctx, const cell_t *params) static cell_t Info(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -821,7 +1009,7 @@ static cell_t Info(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[2], &msg); - logger->info(msg); + logger->raw()->info(msg); return 0; } @@ -831,7 +1019,7 @@ static cell_t Info(IPluginContext *ctx, const cell_t *params) static cell_t InfoEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -844,13 +1032,35 @@ static cell_t InfoEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); return 0; } - logger->info(msg); + logger->raw()->info(msg); + return 0; +} + +/** + * public native void InfoAmxTpl(const char[] fmt, any ...); + */ +static cell_t InfoAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 2); + if (eh.HasException()) + { + return 0; + } + + logger->raw()->info(msg); return 0; } @@ -860,7 +1070,7 @@ static cell_t InfoEx(IPluginContext *ctx, const cell_t *params) static cell_t Warn(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -869,7 +1079,7 @@ static cell_t Warn(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[2], &msg); - logger->warn(msg); + logger->raw()->warn(msg); return 0; } @@ -879,7 +1089,7 @@ static cell_t Warn(IPluginContext *ctx, const cell_t *params) static cell_t WarnEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -892,13 +1102,35 @@ static cell_t WarnEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); + return 0; + } + + logger->raw()->warn(msg); + return 0; +} + +/** + * public native void WarnAmxTpl(const char[] fmt, any ...); + */ +static cell_t WarnAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 2); + if (eh.HasException()) + { return 0; } - logger->warn(msg); + logger->raw()->warn(msg); return 0; } @@ -908,7 +1140,7 @@ static cell_t WarnEx(IPluginContext *ctx, const cell_t *params) static cell_t Error(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -917,7 +1149,7 @@ static cell_t Error(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[2], &msg); - logger->error(msg); + logger->raw()->error(msg); return 0; } @@ -927,7 +1159,7 @@ static cell_t Error(IPluginContext *ctx, const cell_t *params) static cell_t ErrorEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -940,13 +1172,35 @@ static cell_t ErrorEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); + return 0; + } + + logger->raw()->error(msg); + return 0; +} + +/** + * public native void ErrorAmxTpl(const char[] fmt, any ...); + */ +static cell_t ErrorAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 2); + if (eh.HasException()) + { return 0; } - logger->error(msg); + logger->raw()->error(msg); return 0; } @@ -956,7 +1210,7 @@ static cell_t ErrorEx(IPluginContext *ctx, const cell_t *params) static cell_t Fatal(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -965,7 +1219,7 @@ static cell_t Fatal(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[2], &msg); - logger->critical(msg); + logger->raw()->critical(msg); return 0; } @@ -975,7 +1229,7 @@ static cell_t Fatal(IPluginContext *ctx, const cell_t *params) static cell_t FatalEx(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -988,13 +1242,35 @@ static cell_t FatalEx(IPluginContext *ctx, const cell_t *params) } catch(const std::exception& e) { - auto loc = log4sp::get_plugin_source_loc(ctx); - logger->log(loc, spdlog::level::err, e.what()); - spdlog::log(loc, spdlog::level::err, e.what()); + logger->error_handler(e.what()); return 0; } - logger->critical(msg); + logger->raw()->critical(msg); + return 0; +} + +/** + * public native void FatalAmxTpl(const char[] fmt, any ...); + */ +static cell_t FatalAmxTpl(IPluginContext *ctx, const cell_t *params) +{ + auto handle = static_cast(params[1]); + auto logger = log4sp::base_logger::read(handle, ctx); + if (logger == nullptr) + { + return 0; + } + + char msg[2048]; + DetectExceptions eh(ctx); + smutils->FormatString(msg, sizeof(msg), ctx, params, 2); + if (eh.HasException()) + { + return 0; + } + + logger->raw()->critical(msg); return 0; } @@ -1004,13 +1280,13 @@ static cell_t FatalEx(IPluginContext *ctx, const cell_t *params) static cell_t Flush(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - logger->flush(); + logger->raw()->flush(); return 0; } @@ -1020,13 +1296,13 @@ static cell_t Flush(IPluginContext *ctx, const cell_t *params) static cell_t GetFlushLevel(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - return logger->flush_level(); + return static_cast(logger->raw()->flush_level()); } /** @@ -1035,7 +1311,7 @@ static cell_t GetFlushLevel(IPluginContext *ctx, const cell_t *params) static cell_t FlushOn(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -1043,32 +1319,23 @@ static cell_t FlushOn(IPluginContext *ctx, const cell_t *params) auto lvl = log4sp::cell_to_level(params[2]); - logger->flush_on(lvl); + logger->raw()->flush_on(lvl); return 0; } -/** - * Backtrace support: https://github.com/gabime/spdlog?tab=readme-ov-file#backtrace-support - * - * efficiently store all debug/trace messages in a circular buffer until needed for debugging. - * - * Debug messages can be stored in a ring buffer instead of being logged immediately. - * This is useful to display debug logs only when needed (e.g. when an error happens). - * When needed, call dump_backtrace() to dump them to your log. - */ /** * public native bool ShouldBacktrace(); */ static cell_t ShouldBacktrace(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - return logger->should_backtrace(); + return static_cast(logger->raw()->should_backtrace()); } /** @@ -1077,7 +1344,7 @@ static cell_t ShouldBacktrace(IPluginContext *ctx, const cell_t *params) static cell_t EnableBacktrace(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; @@ -1085,7 +1352,7 @@ static cell_t EnableBacktrace(IPluginContext *ctx, const cell_t *params) auto num = static_cast(params[2]); - logger->enable_backtrace(num); + logger->raw()->enable_backtrace(num); return 0; } @@ -1095,13 +1362,13 @@ static cell_t EnableBacktrace(IPluginContext *ctx, const cell_t *params) static cell_t DisableBacktrace(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - logger->disable_backtrace(); + logger->raw()->disable_backtrace(); return 0; } @@ -1111,13 +1378,13 @@ static cell_t DisableBacktrace(IPluginContext *ctx, const cell_t *params) static cell_t DumpBacktrace(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - logger->dump_backtrace(); + logger->raw()->dump_backtrace(); return 0; } @@ -1127,54 +1394,20 @@ static cell_t DumpBacktrace(IPluginContext *ctx, const cell_t *params) static cell_t AddSink(IPluginContext *ctx, const cell_t *params) { auto loggerHandle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, loggerHandle); - if (logger == nullptr) + auto loggerAdapterRaw = log4sp::base_logger::read(loggerHandle, ctx); + if (loggerAdapterRaw == nullptr) { return 0; } - auto loggerData = log4sp::logger_handle_manager::instance().get_data(logger->name()); - if (loggerData == nullptr) - { - ctx->ReportError("Fatal internal error, logger data not found. (name='%s', hdl=%X)", logger->name(), static_cast(loggerHandle)); - return 0; - } - auto sinkHandle = static_cast(params[2]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, sinkHandle); - if (sink == nullptr) - { - return 0; - } - - auto sinkData = log4sp::sink_handle_manager::instance().get_data(sink); - if (sinkData == nullptr) - { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(sinkHandle)); - return 0; - } - - bool async = loggerData->is_multi_threaded(); - if (async != sinkData->is_multi_threaded()) + auto sinkAdapterRaw = log4sp::base_sink::read(sinkHandle, ctx); + if (sinkAdapterRaw == nullptr) { - ctx->ReportError("You cannot add a %s sink to a %s logger.", async ? "synchronous" : "asynchronous", async ? "asynchronous" : "synchronous"); return 0; } - if (!async) - { - logger->sinks().push_back(sinkData->sink_ptr()); - return 0; - } - - auto dist_sink = std::dynamic_pointer_cast(logger->sinks().front()); - if (dist_sink == nullptr) - { - ctx->ReportError("Fatal internal error, cannot cast sink to dist_sink. (name='%s', hdl=%X)", logger->name(), static_cast(loggerHandle)); - return 0; - } - - dist_sink->add_sink(sinkData->sink_ptr()); + loggerAdapterRaw->add_sink(sinkAdapterRaw->raw()); return 0; } @@ -1184,105 +1417,60 @@ static cell_t AddSink(IPluginContext *ctx, const cell_t *params) static cell_t DropSink(IPluginContext *ctx, const cell_t *params) { auto loggerHandle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, loggerHandle); - if (logger == nullptr) - { - return 0; - } - - auto loggerData = log4sp::logger_handle_manager::instance().get_data(logger->name()); - if (loggerData == nullptr) + auto loggerAdapterRaw = log4sp::base_logger::read(loggerHandle, ctx); + if (loggerAdapterRaw == nullptr) { - ctx->ReportError("Fatal internal error, logger data not found. (name='%s', hdl=%X)", logger->name(), static_cast(loggerHandle)); return 0; } auto sinkHandle = static_cast(params[2]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, sinkHandle); - if (sink == nullptr) - { - return 0; - } - - auto sinkData = log4sp::sink_handle_manager::instance().get_data(sink); - if (sinkData == nullptr) + auto sinkAdapterRaw = log4sp::base_sink::read(sinkHandle, ctx); + if (sinkAdapterRaw == nullptr) { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(sinkHandle)); return 0; } - if (!loggerData->is_multi_threaded()) - { - auto iterator = std::find(logger->sinks().begin(), logger->sinks().end(), sinkData->sink_ptr()); - if (iterator == logger->sinks().end()) - { - return false; - } - - logger->sinks().erase(iterator); - return true; - } - - auto dist_sink = std::dynamic_pointer_cast(logger->sinks().front()); - if (dist_sink == nullptr) - { - ctx->ReportError("Fatal internal error, cannot cast sink to dist_sink. (name='%s', hdl=%X)", logger->name(), static_cast(loggerHandle)); - return 0; - } - - dist_sink->remove_sink(sinkData->sink_ptr()); - return true; + loggerAdapterRaw->remove_sink(sinkAdapterRaw->raw()); + return 0; } /** - * public native void SetErrorHandler(Log4spErrorCallback callback); + * public native void SetErrorHandler(LoggerErrorHandler handler); * * function void (const char[] msg); */ static cell_t SetErrorHandler(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto logger = log4sp::logger_handle_manager::instance().read_handle(ctx, handle); + auto logger = log4sp::base_logger::read(handle, ctx); if (logger == nullptr) { return 0; } - auto data = log4sp::logger_handle_manager::instance().get_data(logger->name()); - if (data == nullptr) + auto funcId = static_cast(params[2]); + auto function = ctx->GetFunctionById(funcId); + if (function == nullptr) { - ctx->ReportError("Fatal internal error, logger data not found. (name='%s', hdl=%X)", logger->name(), static_cast(handle)); + ctx->ReportError("Invalid error handler function. (funcId=%d)", static_cast(funcId)); return 0; } - auto funcId = static_cast(params[2]); - auto callback = ctx->GetFunctionById(funcId); - if (callback == NULL) + auto forward = forwards->CreateForwardEx(nullptr, ET_Ignore, 1, nullptr, Param_String); + if (forward == nullptr) { - ctx->ReportError("Invalid function id (%X)", static_cast(funcId)); + ctx->ReportError("SM error! Create error handler forward failure."); return 0; } - auto forward = forwards->CreateForwardEx(NULL, ET_Ignore, 1, NULL, Param_String); - if (forward == NULL) - { - ctx->ReportError("Could not create forward."); - return 0; - } - - if (!forward->AddFunction(callback)) + if (!forward->AddFunction(function)) { forwards->ReleaseForward(forward); - ctx->ReportError("Could not add callback."); + ctx->ReportError("SM error! Adding error handler function failed."); return 0; } - data->set_error_handler(forward); - - data->logger()->set_error_handler([forward](const std::string &msg) { - forward->PushString(msg.c_str()); - forward->Execute(); - }); + logger->set_error_forward(forward); return 0; } @@ -1302,27 +1490,38 @@ const sp_nativeinfo_t LoggerNatives[] = {"Logger.Log", Log}, {"Logger.LogEx", LogEx}, + {"Logger.LogAmxTpl", LogAmxTpl}, {"Logger.LogSrc", LogSrc}, {"Logger.LogSrcEx", LogSrcEx}, + {"Logger.LogSrcAmxTpl", LogSrcAmxTpl}, {"Logger.LogLoc", LogLoc}, {"Logger.LogLocEx", LogLocEx}, + {"Logger.LogLocAmxTpl", LogLocAmxTpl}, {"Logger.LogStackTrace", LogStackTrace}, {"Logger.LogStackTraceEx", LogStackTraceEx}, + {"Logger.LogStackTraceAmxTpl", LogStackTraceAmxTpl}, {"Logger.ThrowError", ThrowError}, {"Logger.ThrowErrorEx", ThrowErrorEx}, + {"Logger.ThrowErrorAmxTpl", ThrowErrorAmxTpl}, {"Logger.Trace", Trace}, {"Logger.TraceEx", TraceEx}, + {"Logger.TraceAmxTpl", TraceAmxTpl}, {"Logger.Debug", Debug}, {"Logger.DebugEx", DebugEx}, + {"Logger.DebugAmxTpl", DebugAmxTpl}, {"Logger.Info", Info}, {"Logger.InfoEx", InfoEx}, + {"Logger.InfoAmxTpl", InfoAmxTpl}, {"Logger.Warn", Warn}, {"Logger.WarnEx", WarnEx}, + {"Logger.WarnAmxTpl", WarnAmxTpl}, {"Logger.Error", Error}, {"Logger.ErrorEx", ErrorEx}, + {"Logger.ErrorAmxTpl", ErrorAmxTpl}, {"Logger.Fatal", Fatal}, {"Logger.FatalEx", FatalEx}, + {"Logger.FatalAmxTpl", FatalAmxTpl}, {"Logger.Flush", Flush}, {"Logger.GetFlushLevel", GetFlushLevel}, @@ -1335,6 +1534,6 @@ const sp_nativeinfo_t LoggerNatives[] = {"Logger.DropSink", DropSink}, {"Logger.SetErrorHandler", SetErrorHandler}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/base_file_sink.cpp b/src/natives/sinks/base_file_sink.cpp index 0c4cf8e..0544dfa 100644 --- a/src/natives/sinks/base_file_sink.cpp +++ b/src/natives/sinks/base_file_sink.cpp @@ -1,13 +1,15 @@ #include "spdlog/sinks/basic_file_sink.h" -#include +#include "log4sp/sink_register.h" +#include "log4sp/adapter/single_thread_sink.h" +#include "log4sp/adapter/multi_thread_sink.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // * BaseFileSink Functions /////////////////////////////////////////////////////////////////////////////////////////////////// /** - * public native BaseFileSink(const char[] file, bool truncate = false, bool async = false); + * public native BaseFileSink(const char[] file, bool truncate = false, bool multiThread = false); */ static cell_t BaseFileSink(IPluginContext *ctx, const cell_t *params) { @@ -16,29 +18,27 @@ static cell_t BaseFileSink(IPluginContext *ctx, const cell_t *params) char path[PLATFORM_MAX_PATH]; smutils->BuildPath(Path_Game, path, sizeof(path), "%s", file); - auto truncate = static_cast(params[2]); - bool async = static_cast(params[3]); - auto data = async ? log4sp::sink_handle_manager::instance().create_base_file_sink_st(ctx, path, truncate) : - log4sp::sink_handle_manager::instance().create_base_file_sink_mt(ctx, path, truncate); + std::shared_ptr sinkAdapter; - if (data == nullptr) + auto truncate = static_cast(params[2]); + bool multiThread = static_cast(params[3]); + if (!multiThread) { - return BAD_HANDLE; + auto sink = std::make_shared(path, truncate); + sinkAdapter = log4sp::single_thread_sink::create(sink, ctx); + } + else + { + auto sink = std::make_shared(path, truncate); + sinkAdapter = log4sp::multi_thread_sink::create(sink, ctx); } - return data->handle(); -} - -template -static void GetFilename(IPluginContext *ctx, const cell_t *params, log4sp::sink_handle_data *data) -{ - auto sink = std::dynamic_pointer_cast>(data->sink_ptr()); - if (sink == nullptr) + if (sinkAdapter == nullptr) { - ctx->ReportError("Unable to cast sink to basic_file_sink_%ct.", data->is_multi_threaded() ? 'm' : 's'); - return; + return BAD_HANDLE; } - ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); + + return sinkAdapter->handle(); } /** @@ -47,26 +47,34 @@ static void GetFilename(IPluginContext *ctx, const cell_t *params, log4sp::sink_ static cell_t BaseFileSink_GetFilename(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) + + auto sinkAdapterRaw = log4sp::base_sink::read(handle, ctx); + if (sinkAdapterRaw == nullptr) { return 0; } - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - if (data == nullptr) + if (!sinkAdapterRaw->is_multi_thread()) { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(handle)); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to single thread basic_file_sink."); + return 0; + } + ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); } - - if (!data->is_multi_threaded()) + else { - GetFilename(ctx, params, data); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to multi thread basic_file_sink."); + return 0; + } + ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); } - GetFilename(ctx, params, data); return 0; } @@ -75,5 +83,5 @@ const sp_nativeinfo_t BaseFileSinkNatives[] = {"BaseFileSink.BaseFileSink", BaseFileSink}, {"BaseFileSink.GetFilename", BaseFileSink_GetFilename}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/client_chat_sink.cpp b/src/natives/sinks/client_chat_sink.cpp index f579ac4..62575c6 100644 --- a/src/natives/sinks/client_chat_sink.cpp +++ b/src/natives/sinks/client_chat_sink.cpp @@ -1,50 +1,38 @@ -#include -#include +#include "log4sp/sinks/client_chat_sink.h" + +#include "log4sp/sink_register.h" +#include "log4sp/adapter/single_thread_sink.h" +#include "log4sp/adapter/multi_thread_sink.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // * ClientChatSink Functions /////////////////////////////////////////////////////////////////////////////////////////////////// /** - * public native ClientChatSink(bool async = false); + * public native ClientChatSink(bool multiThread = false); */ static cell_t ClientChatSink(IPluginContext *ctx, const cell_t *params) { - bool async = static_cast(params[1]); - auto data = async ? log4sp::sink_handle_manager::instance().create_client_chat_sink_st(ctx) : - log4sp::sink_handle_manager::instance().create_client_chat_sink_mt(ctx); + std::shared_ptr sinkAdapter; - if (data == nullptr) + bool multiThread = static_cast(params[1]); + if (!multiThread) { - return BAD_HANDLE; + auto sink = std::make_shared(); + sinkAdapter = log4sp::single_thread_sink::create(sink, ctx); } - - return data->handle(); -} - -template -static void SetFilter(IPluginContext *ctx, const cell_t *params, log4sp::sink_handle_data *data) -{ - auto sink = std::dynamic_pointer_cast>(data->sink_ptr()); - if (sink == nullptr) + else { - ctx->ReportError("Unable to cast sink to client_chat_sink_%ct.", data->is_multi_threaded() ? 'm' : 's'); - return; + auto sink = std::make_shared(); + sinkAdapter = log4sp::multi_thread_sink::create(sink, ctx); } - auto funcId = static_cast(params[2]); - auto filter = ctx->GetFunctionById(funcId); - if (filter == NULL) + if (sinkAdapter == nullptr) { - ctx->ReportError("Invalid client chat sink filter. (%d)", funcId); - return; + return BAD_HANDLE; } - if (!sink->set_player_filter(filter)) - { - ctx->ReportError("Sets client chat sink filter failed. (%d)", funcId); - return; - } + return sinkAdapter->handle(); } /** @@ -53,26 +41,52 @@ static void SetFilter(IPluginContext *ctx, const cell_t *params, log4sp::sink_ha static cell_t ClientChatSink_SetFilter(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) + + auto sinkAdapterRaw = log4sp::base_sink::read(handle, ctx); + if (sinkAdapterRaw == nullptr) { return 0; } - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - if (data == nullptr) + auto funcId = static_cast(params[2]); + auto function = ctx->GetFunctionById(funcId); + if (function == nullptr) { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(handle)); + ctx->ReportError("Invalid client chat sink filter function. (funcId=%d)", funcId); return 0; } - if (!data->is_multi_threaded()) + if (!sinkAdapterRaw->is_multi_thread()) { - SetFilter(ctx, params, data); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to single thread client_chat_sink."); + return 0; + } + + if (!sink->set_player_filter(function)) + { + ctx->ReportError("SM error! Adding client chat sink filter function failed."); + return 0; + } + } + else + { + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to multi thread client_chat_sink."); + return 0; + } + + if (!sink->set_player_filter(function)) + { + ctx->ReportError("SM error! Adding client chat sink filter function failed."); + return 0; + } } - SetFilter(ctx, params, data); return 0; } @@ -81,5 +95,5 @@ const sp_nativeinfo_t ClientChatSinkNatives[] = {"ClientChatSink.ClientChatSink", ClientChatSink}, {"ClientChatSink.SetFilter", ClientChatSink_SetFilter}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/client_console_sink.cpp b/src/natives/sinks/client_console_sink.cpp index b5e212c..a1ef72f 100644 --- a/src/natives/sinks/client_console_sink.cpp +++ b/src/natives/sinks/client_console_sink.cpp @@ -1,50 +1,38 @@ -#include -#include +#include "log4sp/sinks/client_console_sink.h" + +#include "log4sp/sink_register.h" +#include "log4sp/adapter/single_thread_sink.h" +#include "log4sp/adapter/multi_thread_sink.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // * ClientConsoleSink Functions /////////////////////////////////////////////////////////////////////////////////////////////////// /** - * public native ClientConsoleSink(bool async = false); + * public native ClientConsoleSink(bool multiThread = false); */ static cell_t ClientConsoleSink(IPluginContext *ctx, const cell_t *params) { - bool async = static_cast(params[1]); - auto data = async ? log4sp::sink_handle_manager::instance().create_client_console_sink_st(ctx) : - log4sp::sink_handle_manager::instance().create_client_console_sink_mt(ctx); + std::shared_ptr sinkAdapter; - if (data == nullptr) + bool multiThread = static_cast(params[1]); + if (!multiThread) { - return BAD_HANDLE; + auto sink = std::make_shared(); + sinkAdapter = log4sp::single_thread_sink::create(sink, ctx); } - - return data->handle(); -} - -template -static void SetFilter(IPluginContext *ctx, const cell_t *params, log4sp::sink_handle_data *data) -{ - auto sink = std::dynamic_pointer_cast>(data->sink_ptr()); - if (sink == nullptr) + else { - ctx->ReportError("Unable to cast sink to client_console_sink_%ct.", data->is_multi_threaded() ? 'm' : 's'); - return; + auto sink = std::make_shared(); + sinkAdapter = log4sp::multi_thread_sink::create(sink, ctx); } - auto funcId = static_cast(params[2]); - auto filter = ctx->GetFunctionById(funcId); - if (filter == NULL) + if (sinkAdapter == nullptr) { - ctx->ReportError("Invalid client console sink filter. (%d)", funcId); - return; + return BAD_HANDLE; } - if (!sink->set_player_filter(filter)) - { - ctx->ReportError("Sets client console sink filter failed. (%d)", funcId); - return; - } + return sinkAdapter->handle(); } /** @@ -53,26 +41,52 @@ static void SetFilter(IPluginContext *ctx, const cell_t *params, log4sp::sink_ha static cell_t ClientConsoleSink_SetFilter(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) + + auto sinkAdapterRaw = log4sp::base_sink::read(handle, ctx); + if (sinkAdapterRaw == nullptr) { return 0; } - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - if (data == nullptr) + auto funcId = static_cast(params[2]); + auto function = ctx->GetFunctionById(funcId); + if (function == nullptr) { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(handle)); + ctx->ReportError("Invalid client console sink filter function. (funcId=%d)", funcId); return 0; } - if (!data->is_multi_threaded()) + if (!sinkAdapterRaw->is_multi_thread()) { - SetFilter(ctx, params, data); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to single thread client_console_sink."); + return 0; + } + + if (!sink->set_player_filter(function)) + { + ctx->ReportError("SM error! Adding client chat sink filter function failed."); + return 0; + } + } + else + { + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to multi thread client_console_sink."); + return 0; + } + + if (!sink->set_player_filter(function)) + { + ctx->ReportError("SM error! Adding client chat sink filter function failed."); + return 0; + } } - SetFilter(ctx, params, data); return 0; } @@ -81,5 +95,5 @@ const sp_nativeinfo_t ClientConsoleSinkNatives[] = {"ClientConsoleSink.ClientConsoleSink", ClientConsoleSink}, {"ClientConsoleSink.SetFilter", ClientConsoleSink_SetFilter}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/daily_file_sink.cpp b/src/natives/sinks/daily_file_sink.cpp index a8b970d..5468ef5 100644 --- a/src/natives/sinks/daily_file_sink.cpp +++ b/src/natives/sinks/daily_file_sink.cpp @@ -1,6 +1,8 @@ #include "spdlog/sinks/daily_file_sink.h" -#include +#include "log4sp/sink_register.h" +#include "log4sp/adapter/single_thread_sink.h" +#include "log4sp/adapter/multi_thread_sink.h" /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -13,7 +15,7 @@ * int rotationMinute = 0, * bool truncate = false, * int maxFiles = 0, - * bool async = false + * bool multiThread = false * ); */ static cell_t DailyFileSink(IPluginContext *ctx, const cell_t *params) @@ -23,7 +25,7 @@ static cell_t DailyFileSink(IPluginContext *ctx, const cell_t *params) char path[PLATFORM_MAX_PATH]; smutils->BuildPath(Path_Game, path, sizeof(path), "%s", file); - auto rotationHour = static_cast(params[2]); + auto rotationHour = static_cast(params[2]); auto rotationMinute = static_cast(params[3]); if (rotationHour < 0 || rotationHour > 23 || rotationMinute < 0 || rotationMinute > 59) { @@ -31,30 +33,28 @@ static cell_t DailyFileSink(IPluginContext *ctx, const cell_t *params) return BAD_HANDLE; } - auto truncate = static_cast(params[4]); - auto maxFiles = static_cast(params[5]); - bool async = static_cast(params[6]); - auto data = async ? log4sp::sink_handle_manager::instance().create_daily_file_sink_st(ctx, path, rotationHour, rotationMinute, truncate, maxFiles) : - log4sp::sink_handle_manager::instance().create_daily_file_sink_mt(ctx, path, rotationHour, rotationMinute, truncate, maxFiles); + std::shared_ptr sinkAdapter; - if (data == nullptr) + auto truncate = static_cast(params[4]); + auto maxFiles = static_cast(params[5]); + bool multiThread = static_cast(params[6]); + if (!multiThread) { - return BAD_HANDLE; + auto sink = std::make_shared(path, rotationHour, rotationMinute, truncate, maxFiles); + sinkAdapter = log4sp::single_thread_sink::create(sink, ctx); + } + else + { + auto sink = std::make_shared(path, rotationHour, rotationMinute, truncate, maxFiles); + sinkAdapter = log4sp::multi_thread_sink::create(sink, ctx); } - return data->handle(); -} - -template -static void GetFilename(IPluginContext *ctx, const cell_t *params, log4sp::sink_handle_data *data) -{ - auto sink = std::dynamic_pointer_cast>(data->sink_ptr()); - if (sink == nullptr) + if (sinkAdapter == nullptr) { - ctx->ReportError("Unable to cast sink to daily_file_sink_%ct.", data->is_multi_threaded() ? 'm' : 's'); - return; + return BAD_HANDLE; } - ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); + + return sinkAdapter->handle(); } /** @@ -63,26 +63,34 @@ static void GetFilename(IPluginContext *ctx, const cell_t *params, log4sp::sink_ static cell_t DailyFileSink_GetFilename(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) + + auto sinkAdapterRaw = log4sp::base_sink::read(handle, ctx); + if (sinkAdapterRaw == nullptr) { return 0; } - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - if (data == nullptr) + if (!sinkAdapterRaw->is_multi_thread()) { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(handle)); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to single thread daily_file_sink."); + return 0; + } + ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); } - - if (!data->is_multi_threaded()) + else { - GetFilename(ctx, params, data); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to multi thread daily_file_sink."); + return 0; + } + ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); } - GetFilename(ctx, params, data); return 0; } @@ -91,5 +99,5 @@ const sp_nativeinfo_t DailyFileSinkNatives[] = {"DailyFileSink.DailyFileSink", DailyFileSink}, {"DailyFileSink.GetFilename", DailyFileSink_GetFilename}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/rorating_file_sink.cpp b/src/natives/sinks/rorating_file_sink.cpp index 113c32d..b8ec7bb 100644 --- a/src/natives/sinks/rorating_file_sink.cpp +++ b/src/natives/sinks/rorating_file_sink.cpp @@ -1,6 +1,8 @@ #include "spdlog/sinks/rotating_file_sink.h" -#include +#include "log4sp/sink_register.h" +#include "log4sp/adapter/single_thread_sink.h" +#include "log4sp/adapter/multi_thread_sink.h" /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -12,7 +14,7 @@ * const int maxFileSize, * const int maxFiles, * bool rotateOnOpen = false, - * bool async = false + * bool multiThread = false * ); */ static cell_t RotatingFileSink(IPluginContext *ctx, const cell_t *params) @@ -36,29 +38,27 @@ static cell_t RotatingFileSink(IPluginContext *ctx, const cell_t *params) return BAD_HANDLE; } - auto rotateOnOpen = static_cast(params[4]); - bool async = static_cast(params[5]); - auto data = async ? log4sp::sink_handle_manager::instance().create_rotating_file_sink_st(ctx, path, maxFileSize, maxFiles, rotateOnOpen) : - log4sp::sink_handle_manager::instance().create_rotating_file_sink_mt(ctx, path, maxFileSize, maxFiles, rotateOnOpen); + std::shared_ptr sinkAdapter; - if (data == nullptr) + auto rotateOnOpen = static_cast(params[4]); + bool multiThread = static_cast(params[5]); + if (!multiThread) { - return BAD_HANDLE; + auto sink = std::make_shared(path, maxFileSize, maxFiles, rotateOnOpen); + sinkAdapter = log4sp::single_thread_sink::create(sink, ctx); + } + else + { + auto sink = std::make_shared(path, maxFileSize, maxFiles, rotateOnOpen); + sinkAdapter = log4sp::multi_thread_sink::create(sink, ctx); } - return data->handle(); -} - -template -static void GetFilename(IPluginContext *ctx, const cell_t *params, log4sp::sink_handle_data *data) -{ - auto sink = std::dynamic_pointer_cast>(data->sink_ptr()); - if (sink == nullptr) + if (sinkAdapter == nullptr) { - ctx->ReportError("Unable to cast sink to rotating_file_sink_%ct.", data->is_multi_threaded() ? 'm' : 's'); - return; + return BAD_HANDLE; } - ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); + + return sinkAdapter->handle(); } /** @@ -67,26 +67,34 @@ static void GetFilename(IPluginContext *ctx, const cell_t *params, log4sp::sink_ static cell_t RotatingFileSink_GetFilename(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) + + auto sinkAdapterRaw = log4sp::base_sink::read(handle, ctx); + if (sinkAdapterRaw == nullptr) { return 0; } - auto data = log4sp::sink_handle_manager::instance().get_data(sink); - if (data == nullptr) + if (!sinkAdapterRaw->is_multi_thread()) { - ctx->ReportError("Fatal internal error, sink data not found. (hdl=%X)", static_cast(handle)); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to single threaded rotating_file_sink."); + return 0; + } + ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); } - - if (!data->is_multi_threaded()) + else { - GetFilename(ctx, params, data); - return 0; + auto sink = std::dynamic_pointer_cast(sinkAdapterRaw->raw()); + if (sink == nullptr) + { + ctx->ReportError("Unable to cast sink to multi threaded rotating_file_sink."); + return 0; + } + ctx->StringToLocal(params[2], params[3], sink->filename().c_str()); } - GetFilename(ctx, params, data); return 0; } @@ -99,7 +107,7 @@ static cell_t RotatingFileSink_CalcFilename(IPluginContext *ctx, const cell_t *p ctx->LocalToString(params[1], &file); auto index = static_cast(params[2]); - auto filename = spdlog::sinks::rotating_file_sink::calc_filename(file, index); + auto filename = spdlog::sinks::rotating_file_sink_st::calc_filename(file, index); ctx->StringToLocal(params[3], params[4], filename.c_str()); return 0; } @@ -110,5 +118,5 @@ const sp_nativeinfo_t RotatingFileSinkNatives[] = {"RotatingFileSink.GetFilename", RotatingFileSink_GetFilename}, {"RotatingFileSink.CalcFilename", RotatingFileSink_CalcFilename}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/server_console_sink.cpp b/src/natives/sinks/server_console_sink.cpp index ae3c603..aad76d9 100644 --- a/src/natives/sinks/server_console_sink.cpp +++ b/src/natives/sinks/server_console_sink.cpp @@ -1,31 +1,43 @@ #include "spdlog/sinks/stdout_sinks.h" -#include +#include "log4sp/sink_register.h" +#include "log4sp/adapter/single_thread_sink.h" +#include "log4sp/adapter/multi_thread_sink.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // * ServerConsoleSink Functions /////////////////////////////////////////////////////////////////////////////////////////////////// /** - * public native ServerConsoleSink(bool async = false); + * public native ServerConsoleSink(bool multiThread = false); */ static cell_t ServerConsoleSink(IPluginContext *ctx, const cell_t *params) { - bool async = static_cast(params[1]); - auto data = async ? log4sp::sink_handle_manager::instance().create_server_console_sink_st(ctx) : - log4sp::sink_handle_manager::instance().create_server_console_sink_mt(ctx); + std::shared_ptr sinkAdapter; - if (data == nullptr) + bool multiThread = static_cast(params[1]); + if (!multiThread) + { + auto sink = std::make_shared(); + sinkAdapter = log4sp::single_thread_sink::create(sink, ctx); + } + else + { + auto sink = std::make_shared(); + sinkAdapter = log4sp::multi_thread_sink::create(sink, ctx); + } + + if (sinkAdapter == nullptr) { return BAD_HANDLE; } - return data->handle(); + return sinkAdapter->handle(); } const sp_nativeinfo_t ServerConsoleSinkNatives[] = { {"ServerConsoleSink.ServerConsoleSink", ServerConsoleSink}, - {NULL, NULL} + {nullptr, nullptr} }; diff --git a/src/natives/sinks/sink.cpp b/src/natives/sinks/sink.cpp index b53e00a..5c4a225 100644 --- a/src/natives/sinks/sink.cpp +++ b/src/natives/sinks/sink.cpp @@ -1,17 +1,10 @@ #include "spdlog/sinks/sink.h" -#include -#include +#include "log4sp/utils.h" +#include "log4sp/sink_register.h" +#include "log4sp/adapter/base_sink.h" -/** - * 每一个手动创建的 sink 都会交给注册器管理 - * 添加到 logger 时会从注册器中获取智能指针 - * 当用户 delete 时,注册器会删除 sink 的引用 - * 但不代表这个 sink 会立刻被释放 - * 如果没有任何 logger 引用这个 sink - * 即智能指针的引用数为 0,这个 sink 才会被立马释放 - */ /////////////////////////////////////////////////////////////////////////////////////////////////// // * Sink Functions /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -21,13 +14,13 @@ static cell_t GetLevel(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); + auto sink = log4sp::base_sink::read(handle, ctx); if (sink == nullptr) { return 0; } - return sink->level(); + return sink->raw()->level(); } /** @@ -36,7 +29,7 @@ static cell_t GetLevel(IPluginContext *ctx, const cell_t *params) static cell_t SetLevel(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); + auto sink = log4sp::base_sink::read(handle, ctx); if (sink == nullptr) { return 0; @@ -44,29 +37,17 @@ static cell_t SetLevel(IPluginContext *ctx, const cell_t *params) auto lvl = log4sp::cell_to_level(params[2]); - sink->set_level(lvl); + sink->raw()->set_level(lvl); return 0; } - -/** - * set formatting for the sinks in this logger. - * each sink will get a separate instance of the formatter object. - * - * set formatting for the sinks in this logger. - * equivalent to - * set_formatter(make_unique(pattern, time_type)) - * Note: each sink will get a new instance of a formatter object, replacing the old one. - * - * pattern flags (https://github.com/gabime/spdlog/wiki/3.-Custom-formatting#pattern-flags) - */ /** * public native void SetPattern(const char[] pattern); */ static cell_t SetPattern(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); + auto sink = log4sp::base_sink::read(handle, ctx); if (sink == nullptr) { return 0; @@ -75,7 +56,7 @@ static cell_t SetPattern(IPluginContext *ctx, const cell_t *params) char *pattern; ctx->LocalToString(params[2], &pattern); - sink->set_pattern(pattern); + sink->raw()->set_pattern(pattern); return 0; } @@ -85,7 +66,7 @@ static cell_t SetPattern(IPluginContext *ctx, const cell_t *params) static cell_t ShouldLog(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); + auto sink = log4sp::base_sink::read(handle, ctx); if (sink == nullptr) { return 0; @@ -93,7 +74,7 @@ static cell_t ShouldLog(IPluginContext *ctx, const cell_t *params) auto lvl = log4sp::cell_to_level(params[2]); - return sink->should_log(lvl); + return sink->raw()->should_log(lvl); } /** @@ -102,7 +83,7 @@ static cell_t ShouldLog(IPluginContext *ctx, const cell_t *params) static cell_t Log(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); + auto sink = log4sp::base_sink::read(handle, ctx); if (sink == nullptr) { return 0; @@ -116,60 +97,7 @@ static cell_t Log(IPluginContext *ctx, const cell_t *params) char *msg; ctx->LocalToString(params[4], &msg); - sink->log(spdlog::details::log_msg(name, lvl, msg)); - return 0; -} - -/** - * public native void LogSrc(const char[] name, LogLevel lvl, const char[] msg); - */ -static cell_t LogSrc(IPluginContext *ctx, const cell_t *params) -{ - auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) - { - return 0; - } - - char *name; - ctx->LocalToString(params[2], &name); - - auto lvl = log4sp::cell_to_level(params[3]); - - char *msg; - ctx->LocalToString(params[4], &msg); - - auto loc = log4sp::get_plugin_source_loc(ctx); - sink->log(spdlog::details::log_msg(loc, name, lvl, msg)); - return 0; -} - -/** - * public native void LogLoc(const char[] file, int line, const char[] func, const char[] name, LogLevel lvl, const char[] msg); - */ -static cell_t LogLoc(IPluginContext *ctx, const cell_t *params) -{ - auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); - if (sink == nullptr) - { - return 0; - } - - char *file, *func, *msg; - ctx->LocalToString(params[2], &file); - int line = params[3]; - ctx->LocalToString(params[4], &func); - char *name; - ctx->LocalToString(params[5], &name); - - auto lvl = log4sp::cell_to_level(params[6]); - - ctx->LocalToString(params[7], &msg); - - spdlog::source_loc loc = {file, line, func}; - sink->log(spdlog::details::log_msg(loc, name, lvl, msg)); + sink->raw()->log(spdlog::details::log_msg(name, lvl, msg)); return 0; } @@ -179,13 +107,13 @@ static cell_t LogLoc(IPluginContext *ctx, const cell_t *params) static cell_t Flush(IPluginContext *ctx, const cell_t *params) { auto handle = static_cast(params[1]); - auto sink = log4sp::sink_handle_manager::instance().read_handle(ctx, handle); + auto sink = log4sp::base_sink::read(handle, ctx); if (sink == nullptr) { return 0; } - sink->flush(); + sink->raw()->flush(); return 0; } @@ -196,12 +124,8 @@ const sp_nativeinfo_t SinkNatives[] = {"Sink.SetLevel", SetLevel}, {"Sink.SetPattern", SetPattern}, {"Sink.ShouldLog", ShouldLog}, - {"Sink.Log", Log}, - {"Sink.LogSrc", LogSrc}, - {"Sink.LogLoc", LogLoc}, - {"Sink.Flush", Flush}, - {NULL, NULL} + {nullptr, nullptr} };