概述
mediasoup是一个基于WebRTC的sfu服务器框架,它允许开发人员构建实时通信应用程序。它包含许多模块和组件,其中之一是日志模块。
mediasoup的日志模块用于记录系统的运行日志和调试信息。它可以帮助开发人员在开发和调试过程中跟踪和分析问题。日志模块可以记录各种级别的日志,如错误日志、警告日志、信息日志和调试日志。
使用mediasoup的日志模块,开发人员可以:
-
配置日志级别:可以设置日志级别,只记录特定级别的日志。例如,只记录错误和警告日志,而不记录信息和调试日志。
-
记录日志到文件:可以将日志记录到文件中,以便长期存档和分析。
-
自定义日志输出:可以自定义日志输出格式和方式。开发人员可以选择将日志输出到控制台、文件还是其他位置。
-
进行远程日志记录:可以将日志发送到远程服务器进行集中管理和分析。
日志模块是mediasoup的一个重要组成部分,它为开发人员提供了丰富的日志记录和分析功能,以帮助他们构建稳定和可靠的实时通信应用程序。使用日志模块,开发人员可以更轻松地诊断和解决问题,并提供更好的用户体验。
日志level
enum class LogLevel : uint8_t
{LOG_DEBUG = 3,LOG_WARN = 2,LOG_ERROR = 1,LOG_NONE = 0
};
Value | Description |
---|---|
“debug” | Log all severities. |
“warn” | Log “warn” and “error” severities. |
“error” | Log “error” severity. |
“none” | Do not log anything |
日志LogTags
struct LogTags{bool info{ false };bool ice{ false };bool dtls{ false };bool rtp{ false };bool srtp{ false };bool rtcp{ false };bool rtx{ false };bool bwe{ false };bool score{ false };bool simulcast{ false };bool svc{ false };bool sctp{ false };bool message{ false };};
Value | Description |
---|---|
“info” | Logs about software/library versions, configuration and process information. |
“ice” | Logs about ICE. |
“dtls” | Logs about DTLS. |
“rtp” | Logs about RTP. |
“srtp” | Logs about SRTP encryption/decryption. |
“rtcp” | Logs about RTCP. |
“rtx” | Logs about RTP retransmission, including NACK/PLI/FIR. |
“bwe” | Logs about transport bandwidth estimation. |
“score” | Logs related to the scores of Producers and Consumers. |
“simulcast” | Logs about video simulcast. |
“svc” | Logs about video SVC. |
“sctp” | Logs about SCTP (DataChannel). |
“message” | Logs about messages (can be SCTP messages or direct messages). |
mediasoup生成的所有日志都有一个以“mediasoup”加冒号开头的命名空间,后面是以大写字母加冒号表示的日志严重性(就像“warn”或“error”一样),后面是内部组件名称(如果有)和日志消息。
media worker 子进程生成的日志消息应该得到特殊处理。如果它们的严重性等于或高于给定的logLevel,就会生成它们,但如果DEBUG环境变量的值与其命名空间匹配,就会记录它们。
media worker 子进程生成的日志可以具有以下命名空间(其中NNNNN是子进程PID):
“mediasoup:worker[pid:NNNNNN]”
“mediasoup:WARN:worker[pid:NNNNNN]”
“mediasoup:ERROR:worker[pid:NNNNNN]”
mediasoup启动日志
mediasoup:worker[pid:80653] mediasoup-worker::main() | starting mediasoup-worker process [version:3.0.0-dev] +0ms
mediasoup:worker[pid:80653] mediasoup-worker::main() | little-endian CPU detected +0ms
mediasoup:worker[pid:80653] mediasoup-worker::main() | 64 bits architecture detected +1ms
mediasoup:worker[pid:80653] Settings::PrintConfiguration() | <configuration> +0ms
mediasoup:worker[pid:80653] Settings::PrintConfiguration() | logLevel : debug +0ms
mediasoup:worker[pid:80653] Settings::PrintConfiguration() | logTags : info,simulcast +0ms
mediasoup:worker[pid:80653] Settings::PrintConfiguration() | rtcMinPort : 40000 +0ms
mediasoup:worker[pid:80653] Settings::PrintConfiguration() | rtcMaxPort : 49999 +0ms
mediasoup:worker[pid:80653] Settings::PrintConfiguration() | </configuration> +0ms
mediasoup:worker[pid:80653] DepLibUV::PrintVersion() | libuv version: "1.27.0" +0ms
mediasoup:worker[pid:80653] DepOpenSSL::ClassInit() | openssl version: "OpenSSL 1.1.1b 26 Feb 2019" +0ms
mediasoup:worker[pid:80653] DepLibSRTP::ClassInit() | libsrtp version: "libsrtp 2.0.0" +0ms
mediasoup:Worker worker process running [pid:80653] +28ms
mediasoup:Worker createRouter() +1m
mediasoup:Channel[pid:80653] request() [method:worker.createRouter, id:1] +1m
mediasoup:Channel[pid:80653] request succeeded [method:worker.createRouter, id:1] +4ms
mediasoup:Router constructor() +0ms
mediasoup:Channel[pid:80653] request() [method:router.createWebRtcTransport, id:3] +360ms
mediasoup:Channel[pid:80653] request succeeded [method:router.createWebRtcTransport, id:3] +4ms
mediasoup:Transport constructor() +0ms
mediasoup:WebRtcTransport constructor() +0ms
mediasoup:Transport setMaxIncomingBitrate() [bitrate:1500000] +4ms
mediasoup:Channel[pid:80653] request() [method:transport.setMaxIncomingBitrate, id:4] +8ms
mediasoup:Channel[pid:80653] request succeeded [method:transport.setMaxIncomingBitrate, id:4] +2ms
日志相关接口定义
#ifdef MS_LOG_TRACE#define MS_TRACE() \do \{ \if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG) \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D(trace) " _MS_LOG_STR, _MS_LOG_ARG); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \} \while (false)#define MS_TRACE_STD() \do \{ \if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG) \{ \std::fprintf(stdout, "(trace) " _MS_LOG_STR _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG); \std::fflush(stdout); \} \} \while (false)
#else#define MS_TRACE() {}#define MS_TRACE_STD() {}
#endif#define MS_HAS_DEBUG_TAG(tag) \(Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED(tag))#define MS_HAS_WARN_TAG(tag) \(Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED(tag))#define MS_DEBUG_TAG(tag, desc, ...) \do \{ \if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED(tag)) \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \} \while (false)#define MS_DEBUG_TAG_STD(tag, desc, ...) \do \{ \if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED(tag)) \{ \std::fprintf(stdout, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stdout); \} \} \while (false)#define MS_WARN_TAG(tag, desc, ...) \do \{ \if (Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED(tag)) \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \} \while (false)#define MS_WARN_TAG_STD(tag, desc, ...) \do \{ \if (Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED(tag)) \{ \std::fprintf(stderr, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stderr); \} \} \while (false)#define MS_DEBUG_2TAGS(tag1, tag2, desc, ...) \do \{ \if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED_2(tag1, tag2)) \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \} \while (false)#define MS_DEBUG_2TAGS_STD(tag1, tag2, desc, ...) \do \{ \if (Settings::configuration.logLevel == LogLevel::LOG_DEBUG && _MS_TAG_ENABLED_2(tag1, tag2)) \{ \std::fprintf(stdout, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stdout); \} \} \while (false)#define MS_WARN_2TAGS(tag1, tag2, desc, ...) \do \{ \if (Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED_2(tag1, tag2)) \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \} \while (false)#define MS_WARN_2TAGS_STD(tag1, tag2, desc, ...) \do \{ \if (Settings::configuration.logLevel >= LogLevel::LOG_WARN && _MS_TAG_ENABLED_2(tag1, tag2)) \{ \std::fprintf(stderr, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stderr); \} \} \while (false)#if MS_LOG_DEV_LEVEL == 3#define MS_DEBUG_DEV(desc, ...) \do \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "D" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \while (false)#define MS_DEBUG_DEV_STD(desc, ...) \do \{ \std::fprintf(stdout, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stdout); \} \while (false)
#else#define MS_DEBUG_DEV(desc, ...) {}#define MS_DEBUG_DEV_STD(desc, ...) {}
#endif#if MS_LOG_DEV_LEVEL >= 2#define MS_WARN_DEV(desc, ...) \do \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "W" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \while (false)#define MS_WARN_DEV_STD(desc, ...) \do \{ \std::fprintf(stderr, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stderr); \} \while (false)
#else#define MS_WARN_DEV(desc, ...) {}#define MS_WARN_DEV_STD(desc, ...) {}
#endif#define MS_DUMP(desc, ...) \do \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "X" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \while (false)#define MS_DUMP_STD(desc, ...) \do \{ \std::fprintf(stdout, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stdout); \} \while (false)#define MS_DUMP_DATA(data, len) \do \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "X(data) " _MS_LOG_STR, _MS_LOG_ARG); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \size_t bufferDataLen{ 0 }; \for (size_t i{0}; i < len; ++i) \{ \if (i % 8 == 0) \{ \if (bufferDataLen != 0) \{ \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(bufferDataLen)); \bufferDataLen = 0; \} \const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "X%06X ", static_cast<unsigned int>(i)); \bufferDataLen += loggerWritten; \} \const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "%02X ", static_cast<unsigned char>(data[i])); \bufferDataLen += loggerWritten; \} \if (bufferDataLen != 0) \{ \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(bufferDataLen)); \} \} \while (false)#define MS_DUMP_DATA_STD(data, len) \do \{ \std::fprintf(stdout, "(data) " _MS_LOG_STR _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG); \size_t bufferDataLen{ 0 }; \for (size_t i{0}; i < len; ++i) \{ \if (i % 8 == 0) \{ \if (bufferDataLen != 0) \{ \Logger::buffer[bufferDataLen] = '\0'; \std::fprintf(stdout, "%s", Logger::buffer); \bufferDataLen = 0; \} \const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "\n%06X ", static_cast<unsigned int>(i)); \bufferDataLen += loggerWritten; \} \const int loggerWritten = std::snprintf(Logger::buffer + bufferDataLen, Logger::BufferSize, "%02X ", static_cast<unsigned char>(data[i])); \bufferDataLen += loggerWritten; \} \if (bufferDataLen != 0) \{ \Logger::buffer[bufferDataLen] = '\0'; \std::fprintf(stdout, "%s", Logger::buffer); \} \std::fflush(stdout); \} \while (false)#define MS_ERROR(desc, ...) \do \{ \if (Settings::configuration.logLevel >= LogLevel::LOG_ERROR || MS_LOG_DEV_LEVEL >= 1) \{ \const int loggerWritten = std::snprintf(Logger::buffer, Logger::BufferSize, "E" _MS_LOG_STR_DESC desc, _MS_LOG_ARG, ##__VA_ARGS__); \Logger::channel->SendLog(Logger::buffer, static_cast<uint32_t>(loggerWritten)); \} \} \while (false)#define MS_ERROR_STD(desc, ...) \do \{ \if (Settings::configuration.logLevel >= LogLevel::LOG_ERROR || MS_LOG_DEV_LEVEL >= 1) \{ \std::fprintf(stderr, _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stderr); \} \} \while (false)#define MS_ABORT(desc, ...) \do \{ \std::fprintf(stderr, "(ABORT) " _MS_LOG_STR_DESC desc _MS_LOG_SEPARATOR_CHAR_STD, _MS_LOG_ARG, ##__VA_ARGS__); \std::fflush(stderr); \std::abort(); \} \while (false)#define MS_ASSERT(condition, desc, ...) \if (!(condition)) \{ \MS_ABORT("failed assertion `%s': " desc, #condition, ##__VA_ARGS__); \}