{"id":509,"date":"2022-03-08T11:30:05","date_gmt":"2022-03-08T03:30:05","guid":{"rendered":"https:\/\/www.fanyamin.com\/wordpress\/?p=509"},"modified":"2022-03-11T17:06:51","modified_gmt":"2022-03-11T09:06:51","slug":"webrtc-logging-minutes","status":"publish","type":"post","link":"https:\/\/www.fanyamin.com\/wordpress\/?p=509","title":{"rendered":"How to add log to log file in WebRTC library"},"content":{"rendered":"<ol>\n<li>\n<p>\u5148\u5199\u4e00\u4e2a LogSink<\/p>\n<pre><code class=\"language-cpp\">\nclass BweTestLogSink : public rtc::LogSink\n{\npublic:\nBweTestLogSink(const std::string&amp; filepath) { \n  m_stream.open(filepath, std::ios::app | std::ios::out | std::ios::in); \n}\n\n~BweTestLogSink() { \n  m_stream.close(); \n}\n\nvoid OnLogMessage(const std::string&amp; message) override {\n  \/\/std::cout &lt;&lt; message &lt;&lt; std::endl;\n  m_stream &lt;&lt; message;\n}\n\nprivate:\nstd::ofstream m_stream;\n};<\/code><\/pre>\n<\/li>\n<\/ol>\n<pre><code>\n2. \u5c06\u8fd9\u4e2a LogSink \u52a0\u5230 LogMessage \u7684\u8f93\u51fa\u6d41\u4e2d\n\n```cpp\n\/\/\u7a0b\u5e8f\u5f00\u59cb\u540e\n\n\/\/add timestmap, thread into log\nrtc::LogMessage::LogTimestamps(true);\nrtc::LogMessage::LogThreads(true);\n\/\/enable verbose log\nrtc::LogMessage::LogToDebug(rtc::LS_VERBOSE);\n\n\/\/add a file log\nstd::string str = &quot;bwe_trace.log&quot;;\nBweTestLogSink bweLogSink(&amp;str);\nLogMessage::AddLogToStream(&amp;bweLogSink, LS_INFO);\n\n\/\/\u4e5f\u53ef\u4ee5\u7528\u7cfb\u7edf\u63d0\u4f9b\u7684\u6587\u4ef6\u65e5\u5fd7\nFileRotatingLogSink frls(&quot;C:\\\\Users\\\\study\\\\Desktop\\\\log&quot;,&quot;webrtc_log&quot;,1024,2);\nfrls.Init();\n\n\/\/\u5c06\u65e5\u5fd7\u8f93\u51fa\u5230\u65e5\u5fd7\u6587\u4ef6\u4e2d\uff0c\u63a5\u6536WARNING\u53ca\u4ee5\u4e0a\u7ea7\u522b\u7684\u65e5\u5fd7\nLogMessage::AddLogToStream(&amp;frls, WARNING);\n\n\/\/...\n\/\/\u7a0b\u5e8f\u7ed3\u675f\u524d\nLogMessage::RemoveLogToStream(&amp;bweLogSink);<\/code><\/pre>\n<ol start=\"3\">\n<li>\u5728\u60f3\u52a0 log \u7684\u5730\u65b9\u7528 log macro \u5199 log<\/li>\n<\/ol>\n<pre><code class=\"language-cpp\">RTC_LOG(LS_INFO) &lt;&lt; &quot;log something&quot;;<\/code><\/pre>\n<h2>log macro<\/h2>\n<pre><code class=\"language-cpp\">#define RTC_LOG_FILE_LINE(sev, file, line)        \\\n  ::rtc::webrtc_logging_impl::LogCall() &amp;         \\\n      ::rtc::webrtc_logging_impl::LogStreamer&lt;&gt;() \\\n          &lt;&lt; ::rtc::webrtc_logging_impl::LogMetadata(file, line, sev)\n\n#define RTC_LOG(sev)                        \\\n  !rtc::LogMessage::IsNoop&lt;::rtc::sev&gt;() &amp;&amp; \\\n      RTC_LOG_FILE_LINE(::rtc::sev, __FILE__, __LINE__)\n<\/code><\/pre>\n<p>e.g.<\/p>\n<p>void LogPacketResult(PacketResult&amp; packetResult) {<br \/>\nRTC_LOG(LS_VERBOSE) &lt;&lt; &quot;[BWE_LOG] receive_time=&quot; &lt;&lt; packetResult.receive_time.ms()<br \/>\n&lt;&lt; &quot;send_packet, send_time=&quot; &lt;&lt; packetResult.sent_packet.send_time.ms()<br \/>\n&lt;&lt; &quot;, sequence_number=&quot; &lt;&lt; packetResult.sent_packet.sequence_number<br \/>\n&lt;&lt; &quot;, size=&quot; &lt;&lt; ToString(packetResult.sent_packet.size)<br \/>\n&lt;&lt; &quot;, data_in_flight=&quot; &lt;&lt; ToString(packetResult.sent_packet.data_in_flight)<br \/>\n&lt;&lt; &quot;, pacing_info, probe_cluster_id=&quot; &lt;&lt; packetResult.sent_packet.pacing_info.probe_cluster_id<br \/>\n&lt;&lt; &quot;, send_bitrate_bps=&quot; &lt;&lt; packetResult.sent_packet.pacing_info.send_bitrate_bps<br \/>\n&lt;&lt; &quot;, probe_cluster_bytes_sent=&quot; &lt;&lt; packetResult.sent_packet.pacing_info.probe_cluster_bytes_sent;<\/p>\n<p>}<\/p>\n<h2>log stream<\/h2>\n<pre><code class=\"language-cpp\">\n\/\/ Base case: Before the first &lt;&lt; argument.\ntemplate &lt;&gt;\nclass LogStreamer&lt;&gt; final {\n public:\n  template &lt;typename U,\n            typename V = decltype(MakeVal(std::declval&lt;U&gt;())),\n            absl::enable_if_t&lt;std::is_arithmetic&lt;U&gt;::value ||\n                              std::is_enum&lt;U&gt;::value&gt;* = nullptr&gt;\n  RTC_FORCE_INLINE LogStreamer&lt;V&gt; operator&lt;&lt;(U arg) const {\n    return LogStreamer&lt;V&gt;(MakeVal(arg), this);\n  }\n\n  template &lt;typename U,\n            typename V = decltype(MakeVal(std::declval&lt;U&gt;())),\n            absl::enable_if_t&lt;!std::is_arithmetic&lt;U&gt;::value &amp;&amp;\n                              !std::is_enum&lt;U&gt;::value&gt;* = nullptr&gt;\n  RTC_FORCE_INLINE LogStreamer&lt;V&gt; operator&lt;&lt;(const U&amp; arg) const {\n    return LogStreamer&lt;V&gt;(MakeVal(arg), this);\n  }\n\n  template &lt;typename... Us&gt;\n  RTC_FORCE_INLINE static void Call(const Us&amp;... args) {\n    static constexpr LogArgType t[] = {Us::Type()..., LogArgType::kEnd};\n    Log(t, args.GetVal()...);\n  }\n};<\/code><\/pre>\n<h2>Log message<\/h2>\n<pre><code class=\"language-cpp\">\n\/\/ Direct use of this class is deprecated; please use the logging macros\n\/\/ instead.\n\/\/ TODO(bugs.webrtc.org\/9278): Move this class to an unnamed namespace in the\n\/\/ .cc file.\nclass LogMessage {\n public:\n  \/\/ Same as the above, but using a compile-time constant for the logging\n  \/\/ severity. This saves space at the call site, since passing an empty struct\n  \/\/ is generally the same as not passing an argument at all.\n  template &lt;LoggingSeverity S&gt;\n  RTC_NO_INLINE LogMessage(const char* file,\n                           int line,\n                           std::integral_constant&lt;LoggingSeverity, S&gt;)\n      : LogMessage(file, line, S) {}\n\n#if RTC_LOG_ENABLED()\n  LogMessage(const char* file, int line, LoggingSeverity sev);\n  LogMessage(const char* file,\n             int line,\n             LoggingSeverity sev,\n             LogErrorContext err_ctx,\n             int err);\n#if defined(WEBRTC_ANDROID)\n  LogMessage(const char* file, int line, LoggingSeverity sev, const char* tag);\n#endif\n  \/\/ DEPRECATED - DO NOT USE - PLEASE USE THE MACROS INSTEAD OF THE CLASS.\n  \/\/ Android code should use the &#039;const char*&#039; version since tags are static\n  \/\/ and we want to avoid allocating a std::string copy per log line.\n  ABSL_DEPRECATED(&quot;Use RTC_LOG macros instead of accessing this class directly&quot;)\n  LogMessage(const char* file,\n             int line,\n             LoggingSeverity sev,\n             const std::string&amp; tag);\n  ~LogMessage();\n  \/\/...\n  \/\/ String data generated in the constructor, that should be appended to\n  \/\/ the message before output.\n  std::string extra_;\n\n  \/\/ The output streams and their associated severities\n  static LogSink* streams_;\n\n  \/\/ Holds true with high probability if `streams_` is empty, false with high\n  \/\/ probability otherwise. Operated on with std::memory_order_relaxed because\n  \/\/ it&#039;s ok to lose or log some additional statements near the instant streams\n  \/\/ are added\/removed.\n  static std::atomic&lt;bool&gt; streams_empty_;\n\n  \/\/ Flags for formatting options\n  static bool thread_, timestamp_;\n  \/\/...\n  \/\/ The stringbuilder that buffers the formatted message before output\n  rtc::StringBuilder print_stream_;\n  }\n<\/code><\/pre>\n<h2>Log function<\/h2>\n<pre><code class=\"language-cpp\">\nvoid Log(const LogArgType* fmt, ...) {\n  va_list args;\n  va_start(args, fmt);\n\n  LogMetadataErr meta;\n  const char* tag = nullptr;\n  switch (*fmt) {\n    case LogArgType::kLogMetadata: {\n      meta = {va_arg(args, LogMetadata), ERRCTX_NONE, 0};\n      break;\n    }\n    case LogArgType::kLogMetadataErr: {\n      meta = va_arg(args, LogMetadataErr);\n      break;\n    }\n#ifdef WEBRTC_ANDROID\n    case LogArgType::kLogMetadataTag: {\n      const LogMetadataTag tag_meta = va_arg(args, LogMetadataTag);\n      meta = {{nullptr, 0, tag_meta.severity}, ERRCTX_NONE, 0};\n      tag = tag_meta.tag;\n      break;\n    }\n#endif\n    default: {\n      RTC_DCHECK_NOTREACHED();\n      va_end(args);\n      return;\n    }\n  }\n\n  LogMessage log_message(meta.meta.File(), meta.meta.Line(),\n                         meta.meta.Severity(), meta.err_ctx, meta.err);\n  if (tag) {\n    log_message.AddTag(tag);\n  }\n\n  for (++fmt; *fmt != LogArgType::kEnd; ++fmt) {\n    switch (*fmt) {\n      case LogArgType::kInt:\n        log_message.stream() &lt;&lt; va_arg(args, int);\n        break;\n      case LogArgType::kLong:\n        log_message.stream() &lt;&lt; va_arg(args, long);\n        break;\n      case LogArgType::kLongLong:\n        log_message.stream() &lt;&lt; va_arg(args, long long);\n        break;\n      case LogArgType::kUInt:\n        log_message.stream() &lt;&lt; va_arg(args, unsigned);\n        break;\n      case LogArgType::kULong:\n        log_message.stream() &lt;&lt; va_arg(args, unsigned long);\n        break;\n      case LogArgType::kULongLong:\n        log_message.stream() &lt;&lt; va_arg(args, unsigned long long);\n        break;\n      case LogArgType::kDouble:\n        log_message.stream() &lt;&lt; va_arg(args, double);\n        break;\n      case LogArgType::kLongDouble:\n        log_message.stream() &lt;&lt; va_arg(args, long double);\n        break;\n      case LogArgType::kCharP: {\n        const char* s = va_arg(args, const char*);\n        log_message.stream() &lt;&lt; (s ? s : &quot;(null)&quot;);\n        break;\n      }\n      case LogArgType::kStdString:\n        log_message.stream() &lt;&lt; *va_arg(args, const std::string*);\n        break;\n      case LogArgType::kStringView:\n        log_message.stream() &lt;&lt; *va_arg(args, const absl::string_view*);\n        break;\n      case LogArgType::kVoidP:\n        log_message.stream() &lt;&lt; rtc::ToHex(\n            reinterpret_cast&lt;uintptr_t&gt;(va_arg(args, const void*)));\n        break;\n      default:\n        RTC_DCHECK_NOTREACHED();\n        va_end(args);\n        return;\n    }\n  }\n\n  va_end(args);\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5148\u5199\u4e00\u4e2a LogSink class BweTestLogSink : public rtc::LogSink { public: BweTestLogSink(const std::string&amp; filepath) { m_stream.open(filepath, std::ios::app | std::ios::out | std::ios::in); } ~BweTestLogSink() { m_stream.close(); } void OnLogMessage(const std::string&amp; message) override { \/\/std::cout &lt;&lt; message &lt;&lt; std::endl; m_stream &lt;&lt; message; } private: std::ofstream m_stream; }; 2. \u5c06\u8fd9\u4e2a LogSink \u52a0\u5230 LogMessage \u7684\u8f93\u51fa\u6d41\u4e2d &#8220;`cpp \/\/\u7a0b\u5e8f\u5f00\u59cb\u540e \/\/add timestmap, thread into [&hellip;] <a class=\"read-more\" href=\"https:\/\/www.fanyamin.com\/wordpress\/?p=509\" title=\"Permanent Link to: How to add log to log file in WebRTC library\">&rarr;Read&nbsp;more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[],"class_list":["post-509","post","type-post","status-publish","format-standard","hentry","category-webrtc"],"_links":{"self":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/509"}],"collection":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=509"}],"version-history":[{"count":8,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/509\/revisions"}],"predecessor-version":[{"id":559,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/509\/revisions\/559"}],"wp:attachment":[{"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=509"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=509"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fanyamin.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=509"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}