OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | 11 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" |
12 | 12 |
13 #include <atomic> | 13 #include <atomic> |
14 #include <deque> | 14 #include <deque> |
15 #include <functional> | 15 #include <functional> |
16 #include <limits> | 16 #include <limits> |
17 #include <memory> | 17 #include <memory> |
18 #include <utility> | 18 #include <utility> |
19 #include <vector> | 19 #include <vector> |
20 | 20 |
| 21 #include "webrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h" |
| 22 // TODO(eladalon): Remove events/* when the deprecated functions are removed. |
| 23 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_network_adaptation
.h" |
| 24 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_playout.h" |
| 25 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_receive_stream_con
fig.h" |
| 26 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_send_stream_config
.h" |
| 27 #include "webrtc/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h
" |
| 28 #include "webrtc/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h" |
| 29 #include "webrtc/logging/rtc_event_log/events/rtc_event_logging_started.h" |
| 30 #include "webrtc/logging/rtc_event_log/events/rtc_event_logging_stopped.h" |
| 31 #include "webrtc/logging/rtc_event_log/events/rtc_event_probe_cluster_created.h" |
| 32 #include "webrtc/logging/rtc_event_log/events/rtc_event_probe_result_failure.h" |
| 33 #include "webrtc/logging/rtc_event_log/events/rtc_event_probe_result_success.h" |
| 34 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h" |
| 35 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h" |
| 36 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h" |
| 37 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h" |
| 38 #include "webrtc/logging/rtc_event_log/events/rtc_event_video_receive_stream_con
fig.h" |
| 39 #include "webrtc/logging/rtc_event_log/events/rtc_event_video_send_stream_config
.h" |
21 #include "webrtc/logging/rtc_event_log/rtc_stream_config.h" | 40 #include "webrtc/logging/rtc_event_log/rtc_stream_config.h" |
| 41 // TODO(eladalon): Remove these when deprecated functions are removed. |
22 #include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_networ
k_adaptor.h" | 42 #include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_networ
k_adaptor.h" |
23 #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" | 43 #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" |
24 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 44 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
25 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 45 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
26 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" | 46 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" |
27 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" | 47 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" |
28 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h" | 48 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h" |
29 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" | 49 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" |
30 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h" | 50 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h" |
31 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" | 51 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" |
32 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" | 52 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" |
33 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" | 53 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" |
34 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" | 54 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" |
35 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" | 55 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" |
36 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" | 56 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
37 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | 57 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
38 #include "webrtc/rtc_base/checks.h" | 58 #include "webrtc/rtc_base/checks.h" |
39 #include "webrtc/rtc_base/constructormagic.h" | 59 #include "webrtc/rtc_base/constructormagic.h" |
40 #include "webrtc/rtc_base/event.h" | 60 #include "webrtc/rtc_base/event.h" |
41 #include "webrtc/rtc_base/ignore_wundef.h" | |
42 #include "webrtc/rtc_base/logging.h" | 61 #include "webrtc/rtc_base/logging.h" |
43 #include "webrtc/rtc_base/protobuf_utils.h" | 62 #include "webrtc/rtc_base/protobuf_utils.h" |
44 #include "webrtc/rtc_base/ptr_util.h" | 63 #include "webrtc/rtc_base/ptr_util.h" |
45 #include "webrtc/rtc_base/sequenced_task_checker.h" | 64 #include "webrtc/rtc_base/sequenced_task_checker.h" |
46 #include "webrtc/rtc_base/task_queue.h" | 65 #include "webrtc/rtc_base/task_queue.h" |
47 #include "webrtc/rtc_base/thread_annotations.h" | 66 #include "webrtc/rtc_base/thread_annotations.h" |
48 #include "webrtc/rtc_base/timeutils.h" | 67 #include "webrtc/rtc_base/timeutils.h" |
| 68 // TODO(eladalon): Remove this when output is modularized away. |
49 #include "webrtc/system_wrappers/include/file_wrapper.h" | 69 #include "webrtc/system_wrappers/include/file_wrapper.h" |
50 #include "webrtc/typedefs.h" | 70 #include "webrtc/typedefs.h" |
51 | 71 |
52 #ifdef ENABLE_RTC_EVENT_LOG | |
53 // *.pb.h files are generated at build-time by the protobuf compiler. | |
54 RTC_PUSH_IGNORING_WUNDEF() | |
55 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD | |
56 #include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h" | |
57 #else | |
58 #include "webrtc/logging/rtc_event_log/rtc_event_log.pb.h" | |
59 #endif | |
60 RTC_POP_IGNORING_WUNDEF() | |
61 #endif | |
62 | |
63 namespace webrtc { | 72 namespace webrtc { |
64 | 73 |
65 #ifdef ENABLE_RTC_EVENT_LOG | 74 #ifdef ENABLE_RTC_EVENT_LOG |
66 | 75 |
67 namespace { | 76 namespace { |
68 const int kEventsInHistory = 10000; | 77 const int kEventsInHistory = 10000; |
69 | 78 |
70 bool IsConfigEvent(const rtclog::Event& event) { | |
71 rtclog::Event_EventType event_type = event.type(); | |
72 return event_type == rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT || | |
73 event_type == rtclog::Event::VIDEO_SENDER_CONFIG_EVENT || | |
74 event_type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT || | |
75 event_type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT; | |
76 } | |
77 | |
78 // Observe a limit on the number of concurrent logs, so as not to run into | 79 // Observe a limit on the number of concurrent logs, so as not to run into |
79 // OS-imposed limits on open files and/or threads/task-queues. | 80 // OS-imposed limits on open files and/or threads/task-queues. |
80 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. | 81 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. |
81 std::atomic<int> rtc_event_log_count(0); | 82 std::atomic<int> rtc_event_log_count(0); |
82 | 83 |
83 // TODO(eladalon): This class exists because C++11 doesn't allow transferring a | 84 // TODO(eladalon): This class exists because C++11 doesn't allow transferring a |
84 // unique_ptr to a lambda (a copy constructor is required). We should get | 85 // unique_ptr to a lambda (a copy constructor is required). We should get |
85 // rid of this when we move to C++14. | 86 // rid of this when we move to C++14. |
86 template <typename T> | 87 template <typename T> |
87 class ResourceOwningTask final : public rtc::QueuedTask { | 88 class ResourceOwningTask final : public rtc::QueuedTask { |
88 public: | 89 public: |
89 ResourceOwningTask(std::unique_ptr<T> resource, | 90 ResourceOwningTask(std::unique_ptr<T> resource, |
90 std::function<void(std::unique_ptr<T>)> handler) | 91 std::function<void(std::unique_ptr<T>)> handler) |
91 : resource_(std::move(resource)), handler_(handler) {} | 92 : resource_(std::move(resource)), handler_(handler) {} |
92 | 93 |
93 bool Run() override { | 94 bool Run() override { |
94 handler_(std::move(resource_)); | 95 handler_(std::move(resource_)); |
95 return true; | 96 return true; |
96 } | 97 } |
97 | 98 |
98 private: | 99 private: |
99 std::unique_ptr<T> resource_; | 100 std::unique_ptr<T> resource_; |
100 std::function<void(std::unique_ptr<T>)> handler_; | 101 std::function<void(std::unique_ptr<T>)> handler_; |
101 }; | 102 }; |
| 103 |
| 104 std::unique_ptr<RtcEventLogEncoder> CreateEncoder(EncodingType type) { |
| 105 switch (type) { |
| 106 case EncodingType::Legacy: |
| 107 return rtc::MakeUnique<RtcEventLogEncoderLegacy>(); |
| 108 default: |
| 109 LOG(LS_ERROR) << "Unknown RtcEventLog encoder type (" << int(type) << ")"; |
| 110 RTC_NOTREACHED(); |
| 111 } |
| 112 } |
102 } // namespace | 113 } // namespace |
103 | 114 |
104 class RtcEventLogImpl final : public RtcEventLog { | 115 class RtcEventLogImpl final : public RtcEventLog { |
105 public: | 116 public: |
106 RtcEventLogImpl(); | 117 explicit RtcEventLogImpl(std::unique_ptr<RtcEventLogEncoder> event_encoder); |
107 ~RtcEventLogImpl() override; | 118 ~RtcEventLogImpl() override; |
108 | 119 |
109 bool StartLogging(const std::string& file_name, | 120 bool StartLogging(const std::string& file_name, |
110 int64_t max_size_bytes) override; | 121 int64_t max_size_bytes) override; |
111 bool StartLogging(rtc::PlatformFile platform_file, | 122 bool StartLogging(rtc::PlatformFile platform_file, |
112 int64_t max_size_bytes) override; | 123 int64_t max_size_bytes) override; |
113 void StopLogging() override; | 124 void StopLogging() override; |
| 125 void Log(std::unique_ptr<RtcEvent> event) override; |
114 void LogVideoReceiveStreamConfig(const rtclog::StreamConfig& config) override; | 126 void LogVideoReceiveStreamConfig(const rtclog::StreamConfig& config) override; |
115 void LogVideoSendStreamConfig(const rtclog::StreamConfig& config) override; | 127 void LogVideoSendStreamConfig(const rtclog::StreamConfig& config) override; |
116 void LogAudioReceiveStreamConfig(const rtclog::StreamConfig& config) override; | 128 void LogAudioReceiveStreamConfig(const rtclog::StreamConfig& config) override; |
117 void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) override; | 129 void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) override; |
118 // TODO(terelius): This can be removed as soon as the interface has been | 130 // TODO(terelius): This can be removed as soon as the interface has been |
119 // updated. | 131 // updated. |
120 void LogRtpHeader(PacketDirection direction, | 132 void LogRtpHeader(PacketDirection direction, |
121 const uint8_t* header, | 133 const uint8_t* header, |
122 size_t packet_length) override; | 134 size_t packet_length) override; |
123 // TODO(terelius): This can be made private, non-virtual as soon as the | 135 // TODO(terelius): This can be made private, non-virtual as soon as the |
(...skipping 25 matching lines...) Expand all Loading... |
149 int min_probes, | 161 int min_probes, |
150 int min_bytes) override; | 162 int min_bytes) override; |
151 void LogProbeResultSuccess(int id, int bitrate_bps) override; | 163 void LogProbeResultSuccess(int id, int bitrate_bps) override; |
152 void LogProbeResultFailure(int id, | 164 void LogProbeResultFailure(int id, |
153 ProbeFailureReason failure_reason) override; | 165 ProbeFailureReason failure_reason) override; |
154 | 166 |
155 private: | 167 private: |
156 void StartLoggingInternal(std::unique_ptr<FileWrapper> file, | 168 void StartLoggingInternal(std::unique_ptr<FileWrapper> file, |
157 int64_t max_size_bytes); | 169 int64_t max_size_bytes); |
158 | 170 |
159 void StoreEvent(std::unique_ptr<rtclog::Event> event); | |
160 void LogProbeResult(int id, | |
161 rtclog::BweProbeResult::ResultType result, | |
162 int bitrate_bps); | |
163 | |
164 // Appends an event to the output protobuf string, returning true on success. | 171 // Appends an event to the output protobuf string, returning true on success. |
165 // Fails and returns false in case the limit on output size prevents the | 172 // Fails and returns false in case the limit on output size prevents the |
166 // event from being added; in this case, the output string is left unchanged. | 173 // event from being added; in this case, the output string is left unchanged. |
167 bool AppendEventToString(rtclog::Event* event, | 174 // The event is encoded before being appended. |
| 175 bool AppendEventToString(const RtcEvent& event, |
168 ProtoString* output_string) RTC_WARN_UNUSED_RESULT; | 176 ProtoString* output_string) RTC_WARN_UNUSED_RESULT; |
169 | 177 |
170 void LogToMemory(std::unique_ptr<rtclog::Event> event); | 178 void LogToMemory(std::unique_ptr<RtcEvent> event); |
171 | 179 |
172 void StartLogFile(); | 180 void StartLogFile(); |
173 void LogToFile(std::unique_ptr<rtclog::Event> event); | 181 void LogToFile(std::unique_ptr<RtcEvent> event); |
174 void StopLogFile(int64_t stop_time); | 182 void StopLogFile(int64_t stop_time); |
175 | 183 |
176 // Make sure that the event log is "managed" - created/destroyed, as well | 184 // Make sure that the event log is "managed" - created/destroyed, as well |
177 // as started/stopped - from the same thread/task-queue. | 185 // as started/stopped - from the same thread/task-queue. |
178 rtc::SequencedTaskChecker owner_sequence_checker_; | 186 rtc::SequencedTaskChecker owner_sequence_checker_; |
179 | 187 |
180 // History containing all past configuration events. | 188 // History containing all past configuration events. |
181 std::vector<std::unique_ptr<rtclog::Event>> config_history_ | 189 std::vector<std::unique_ptr<RtcEvent>> config_history_ |
182 RTC_ACCESS_ON(task_queue_); | 190 RTC_ACCESS_ON(task_queue_); |
183 | 191 |
184 // History containing the most recent (non-configuration) events (~10s). | 192 // History containing the most recent (non-configuration) events (~10s). |
185 std::deque<std::unique_ptr<rtclog::Event>> history_ | 193 std::deque<std::unique_ptr<RtcEvent>> history_ RTC_ACCESS_ON(task_queue_); |
186 RTC_ACCESS_ON(task_queue_); | |
187 | 194 |
188 std::unique_ptr<FileWrapper> file_ RTC_ACCESS_ON(task_queue_); | 195 std::unique_ptr<FileWrapper> file_ RTC_ACCESS_ON(task_queue_); |
189 | 196 |
190 size_t max_size_bytes_ RTC_ACCESS_ON(task_queue_); | 197 size_t max_size_bytes_ RTC_ACCESS_ON(task_queue_); |
191 size_t written_bytes_ RTC_ACCESS_ON(task_queue_); | 198 size_t written_bytes_ RTC_ACCESS_ON(task_queue_); |
192 | 199 |
| 200 std::unique_ptr<RtcEventLogEncoder> event_encoder_ RTC_ACCESS_ON(task_queue_); |
| 201 |
193 // Keep this last to ensure it destructs first, or else tasks living on the | 202 // Keep this last to ensure it destructs first, or else tasks living on the |
194 // queue might access other members after they've been torn down. | 203 // queue might access other members after they've been torn down. |
195 rtc::TaskQueue task_queue_; | 204 rtc::TaskQueue task_queue_; |
196 | 205 |
197 RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogImpl); | 206 RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogImpl); |
198 }; | 207 }; |
199 | 208 |
200 namespace { | 209 RtcEventLogImpl::RtcEventLogImpl( |
201 // The functions in this namespace convert enums from the runtime format | 210 std::unique_ptr<RtcEventLogEncoder> event_encoder) |
202 // that the rest of the WebRtc project can use, to the corresponding | |
203 // serialized enum which is defined by the protobuf. | |
204 | |
205 rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) { | |
206 switch (rtcp_mode) { | |
207 case RtcpMode::kCompound: | |
208 return rtclog::VideoReceiveConfig::RTCP_COMPOUND; | |
209 case RtcpMode::kReducedSize: | |
210 return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE; | |
211 case RtcpMode::kOff: | |
212 RTC_NOTREACHED(); | |
213 return rtclog::VideoReceiveConfig::RTCP_COMPOUND; | |
214 } | |
215 RTC_NOTREACHED(); | |
216 return rtclog::VideoReceiveConfig::RTCP_COMPOUND; | |
217 } | |
218 | |
219 rtclog::DelayBasedBweUpdate::DetectorState ConvertDetectorState( | |
220 BandwidthUsage state) { | |
221 switch (state) { | |
222 case BandwidthUsage::kBwNormal: | |
223 return rtclog::DelayBasedBweUpdate::BWE_NORMAL; | |
224 case BandwidthUsage::kBwUnderusing: | |
225 return rtclog::DelayBasedBweUpdate::BWE_UNDERUSING; | |
226 case BandwidthUsage::kBwOverusing: | |
227 return rtclog::DelayBasedBweUpdate::BWE_OVERUSING; | |
228 } | |
229 RTC_NOTREACHED(); | |
230 return rtclog::DelayBasedBweUpdate::BWE_NORMAL; | |
231 } | |
232 | |
233 rtclog::BweProbeResult::ResultType ConvertProbeResultType( | |
234 ProbeFailureReason failure_reason) { | |
235 switch (failure_reason) { | |
236 case kInvalidSendReceiveInterval: | |
237 return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL; | |
238 case kInvalidSendReceiveRatio: | |
239 return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO; | |
240 case kTimeout: | |
241 return rtclog::BweProbeResult::TIMEOUT; | |
242 } | |
243 RTC_NOTREACHED(); | |
244 return rtclog::BweProbeResult::SUCCESS; | |
245 } | |
246 | |
247 } // namespace | |
248 | |
249 RtcEventLogImpl::RtcEventLogImpl() | |
250 : file_(FileWrapper::Create()), | 211 : file_(FileWrapper::Create()), |
251 max_size_bytes_(std::numeric_limits<decltype(max_size_bytes_)>::max()), | 212 max_size_bytes_(std::numeric_limits<decltype(max_size_bytes_)>::max()), |
252 written_bytes_(0), | 213 written_bytes_(0), |
| 214 event_encoder_(std::move(event_encoder)), |
253 task_queue_("rtc_event_log") {} | 215 task_queue_("rtc_event_log") {} |
254 | 216 |
255 RtcEventLogImpl::~RtcEventLogImpl() { | 217 RtcEventLogImpl::~RtcEventLogImpl() { |
256 RTC_DCHECK_CALLED_SEQUENTIALLY(&owner_sequence_checker_); | 218 RTC_DCHECK_CALLED_SEQUENTIALLY(&owner_sequence_checker_); |
257 | 219 |
258 // If we're logging to the file, this will stop that. Blocking function. | 220 // If we're logging to the file, this will stop that. Blocking function. |
259 StopLogging(); | 221 StopLogging(); |
260 | 222 |
261 int count = std::atomic_fetch_sub(&rtc_event_log_count, 1) - 1; | 223 int count = std::atomic_fetch_sub(&rtc_event_log_count, 1) - 1; |
262 RTC_DCHECK_GE(count, 0); | 224 RTC_DCHECK_GE(count, 0); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 StopLogFile(stop_time); | 279 StopLogFile(stop_time); |
318 } | 280 } |
319 file_finished.Set(); | 281 file_finished.Set(); |
320 }); | 282 }); |
321 | 283 |
322 file_finished.Wait(rtc::Event::kForever); | 284 file_finished.Wait(rtc::Event::kForever); |
323 | 285 |
324 LOG(LS_INFO) << "WebRTC event log successfully stopped."; | 286 LOG(LS_INFO) << "WebRTC event log successfully stopped."; |
325 } | 287 } |
326 | 288 |
| 289 void RtcEventLogImpl::Log(std::unique_ptr<RtcEvent> event) { |
| 290 RTC_DCHECK(event); |
| 291 |
| 292 auto event_handler = [this](std::unique_ptr<RtcEvent> unencoded_event) { |
| 293 RTC_DCHECK_RUN_ON(&task_queue_); |
| 294 if (file_->is_open()) { |
| 295 LogToFile(std::move(unencoded_event)); |
| 296 } else { |
| 297 LogToMemory(std::move(unencoded_event)); |
| 298 } |
| 299 }; |
| 300 |
| 301 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<RtcEvent>>( |
| 302 std::move(event), event_handler)); |
| 303 } |
| 304 |
327 void RtcEventLogImpl::LogVideoReceiveStreamConfig( | 305 void RtcEventLogImpl::LogVideoReceiveStreamConfig( |
328 const rtclog::StreamConfig& config) { | 306 const rtclog::StreamConfig& config) { |
329 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 307 Log(rtc::MakeUnique<RtcEventVideoReceiveStreamConfig>( |
330 event->set_timestamp_us(rtc::TimeMicros()); | 308 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
331 event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT); | |
332 | |
333 rtclog::VideoReceiveConfig* receiver_config = | |
334 event->mutable_video_receiver_config(); | |
335 receiver_config->set_remote_ssrc(config.remote_ssrc); | |
336 receiver_config->set_local_ssrc(config.local_ssrc); | |
337 | |
338 // TODO(perkj): Add field for rsid. | |
339 receiver_config->set_rtcp_mode(ConvertRtcpMode(config.rtcp_mode)); | |
340 receiver_config->set_remb(config.remb); | |
341 | |
342 for (const auto& e : config.rtp_extensions) { | |
343 rtclog::RtpHeaderExtension* extension = | |
344 receiver_config->add_header_extensions(); | |
345 extension->set_name(e.uri); | |
346 extension->set_id(e.id); | |
347 } | |
348 | |
349 for (const auto& d : config.codecs) { | |
350 rtclog::DecoderConfig* decoder = receiver_config->add_decoders(); | |
351 decoder->set_name(d.payload_name); | |
352 decoder->set_payload_type(d.payload_type); | |
353 if (d.rtx_payload_type != 0) { | |
354 rtclog::RtxMap* rtx = receiver_config->add_rtx_map(); | |
355 rtx->set_payload_type(d.payload_type); | |
356 rtx->mutable_config()->set_rtx_ssrc(config.rtx_ssrc); | |
357 rtx->mutable_config()->set_rtx_payload_type(d.rtx_payload_type); | |
358 } | |
359 } | |
360 StoreEvent(std::move(event)); | |
361 } | 309 } |
362 | 310 |
363 void RtcEventLogImpl::LogVideoSendStreamConfig( | 311 void RtcEventLogImpl::LogVideoSendStreamConfig( |
364 const rtclog::StreamConfig& config) { | 312 const rtclog::StreamConfig& config) { |
365 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 313 Log(rtc::MakeUnique<RtcEventVideoSendStreamConfig>( |
366 event->set_timestamp_us(rtc::TimeMicros()); | 314 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
367 event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT); | |
368 | |
369 rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config(); | |
370 | |
371 // TODO(perkj): rtclog::VideoSendConfig should only contain one SSRC. | |
372 sender_config->add_ssrcs(config.local_ssrc); | |
373 if (config.rtx_ssrc != 0) { | |
374 sender_config->add_rtx_ssrcs(config.rtx_ssrc); | |
375 } | |
376 | |
377 for (const auto& e : config.rtp_extensions) { | |
378 rtclog::RtpHeaderExtension* extension = | |
379 sender_config->add_header_extensions(); | |
380 extension->set_name(e.uri); | |
381 extension->set_id(e.id); | |
382 } | |
383 | |
384 // TODO(perkj): rtclog::VideoSendConfig should contain many possible codec | |
385 // configurations. | |
386 for (const auto& codec : config.codecs) { | |
387 sender_config->set_rtx_payload_type(codec.rtx_payload_type); | |
388 rtclog::EncoderConfig* encoder = sender_config->mutable_encoder(); | |
389 encoder->set_name(codec.payload_name); | |
390 encoder->set_payload_type(codec.payload_type); | |
391 | |
392 if (config.codecs.size() > 1) { | |
393 LOG(WARNING) << "LogVideoSendStreamConfig currently only supports one " | |
394 << "codec. Logging codec :" << codec.payload_name; | |
395 break; | |
396 } | |
397 } | |
398 | |
399 StoreEvent(std::move(event)); | |
400 } | 315 } |
401 | 316 |
402 void RtcEventLogImpl::LogAudioReceiveStreamConfig( | 317 void RtcEventLogImpl::LogAudioReceiveStreamConfig( |
403 const rtclog::StreamConfig& config) { | 318 const rtclog::StreamConfig& config) { |
404 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 319 Log(rtc::MakeUnique<RtcEventAudioReceiveStreamConfig>( |
405 event->set_timestamp_us(rtc::TimeMicros()); | 320 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
406 event->set_type(rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT); | |
407 | |
408 rtclog::AudioReceiveConfig* receiver_config = | |
409 event->mutable_audio_receiver_config(); | |
410 receiver_config->set_remote_ssrc(config.remote_ssrc); | |
411 receiver_config->set_local_ssrc(config.local_ssrc); | |
412 | |
413 for (const auto& e : config.rtp_extensions) { | |
414 rtclog::RtpHeaderExtension* extension = | |
415 receiver_config->add_header_extensions(); | |
416 extension->set_name(e.uri); | |
417 extension->set_id(e.id); | |
418 } | |
419 StoreEvent(std::move(event)); | |
420 } | 321 } |
421 | 322 |
422 void RtcEventLogImpl::LogAudioSendStreamConfig( | 323 void RtcEventLogImpl::LogAudioSendStreamConfig( |
423 const rtclog::StreamConfig& config) { | 324 const rtclog::StreamConfig& config) { |
424 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 325 Log(rtc::MakeUnique<RtcEventAudioSendStreamConfig>( |
425 event->set_timestamp_us(rtc::TimeMicros()); | 326 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
426 event->set_type(rtclog::Event::AUDIO_SENDER_CONFIG_EVENT); | |
427 | |
428 rtclog::AudioSendConfig* sender_config = event->mutable_audio_sender_config(); | |
429 | |
430 sender_config->set_ssrc(config.local_ssrc); | |
431 | |
432 for (const auto& e : config.rtp_extensions) { | |
433 rtclog::RtpHeaderExtension* extension = | |
434 sender_config->add_header_extensions(); | |
435 extension->set_name(e.uri); | |
436 extension->set_id(e.id); | |
437 } | |
438 | |
439 StoreEvent(std::move(event)); | |
440 } | 327 } |
441 | 328 |
442 void RtcEventLogImpl::LogIncomingRtpHeader(const RtpPacketReceived& packet) { | 329 void RtcEventLogImpl::LogIncomingRtpHeader(const RtpPacketReceived& packet) { |
443 LogRtpHeader(kIncomingPacket, packet.data(), packet.size(), | 330 Log(rtc::MakeUnique<RtcEventRtpPacketIncoming>(packet)); |
444 PacedPacketInfo::kNotAProbe); | |
445 } | 331 } |
446 | 332 |
447 void RtcEventLogImpl::LogOutgoingRtpHeader(const RtpPacketToSend& packet, | 333 void RtcEventLogImpl::LogOutgoingRtpHeader(const RtpPacketToSend& packet, |
448 int probe_cluster_id) { | 334 int probe_cluster_id) { |
449 LogRtpHeader(kOutgoingPacket, packet.data(), packet.size(), probe_cluster_id); | 335 Log(rtc::MakeUnique<RtcEventRtpPacketOutgoing>(packet, probe_cluster_id)); |
450 } | 336 } |
451 | 337 |
452 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, | 338 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, |
453 const uint8_t* header, | 339 const uint8_t* header, |
454 size_t packet_length) { | 340 size_t packet_length) { |
455 LogRtpHeader(direction, header, packet_length, PacedPacketInfo::kNotAProbe); | 341 LogRtpHeader(direction, header, packet_length, PacedPacketInfo::kNotAProbe); |
456 } | 342 } |
457 | 343 |
458 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, | 344 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, |
459 const uint8_t* header, | 345 const uint8_t* header, |
460 size_t packet_length, | 346 size_t packet_length, |
461 int probe_cluster_id) { | 347 int probe_cluster_id) { |
462 // Read header length (in bytes) from packet data. | 348 // TODO(eladalon): This is highly inefficient. We're only doing this for |
463 if (packet_length < 12u) { | 349 // the deprecated interface. We should remove this soon. |
464 return; // Don't read outside the packet. | 350 if (direction == PacketDirection::kIncomingPacket) { |
| 351 RtpPacketReceived packet; |
| 352 packet.Parse(header, packet_length); |
| 353 Log(rtc::MakeUnique<RtcEventRtpPacketIncoming>(packet)); |
| 354 } else { |
| 355 RTC_CHECK_EQ(direction, PacketDirection::kOutgoingPacket); |
| 356 RtpPacketToSend packet(nullptr); |
| 357 packet.Parse(header, packet_length); |
| 358 Log(rtc::MakeUnique<RtcEventRtpPacketOutgoing>(packet, probe_cluster_id)); |
465 } | 359 } |
466 const bool x = (header[0] & 0x10) != 0; | |
467 const uint8_t cc = header[0] & 0x0f; | |
468 size_t header_length = 12u + cc * 4u; | |
469 | |
470 if (x) { | |
471 if (packet_length < 12u + cc * 4u + 4u) { | |
472 return; // Don't read outside the packet. | |
473 } | |
474 size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4); | |
475 header_length += (x_len + 1) * 4; | |
476 } | |
477 | |
478 std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event()); | |
479 rtp_event->set_timestamp_us(rtc::TimeMicros()); | |
480 rtp_event->set_type(rtclog::Event::RTP_EVENT); | |
481 rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket); | |
482 rtp_event->mutable_rtp_packet()->set_packet_length(packet_length); | |
483 rtp_event->mutable_rtp_packet()->set_header(header, header_length); | |
484 if (probe_cluster_id != PacedPacketInfo::kNotAProbe) | |
485 rtp_event->mutable_rtp_packet()->set_probe_cluster_id(probe_cluster_id); | |
486 StoreEvent(std::move(rtp_event)); | |
487 } | 360 } |
488 | 361 |
489 void RtcEventLogImpl::LogIncomingRtcpPacket( | 362 void RtcEventLogImpl::LogIncomingRtcpPacket( |
490 rtc::ArrayView<const uint8_t> packet) { | 363 rtc::ArrayView<const uint8_t> packet) { |
491 LogRtcpPacket(kIncomingPacket, packet.data(), packet.size()); | 364 Log(rtc::MakeUnique<RtcEventRtcpPacketIncoming>(packet)); |
492 } | 365 } |
493 | 366 |
494 void RtcEventLogImpl::LogOutgoingRtcpPacket( | 367 void RtcEventLogImpl::LogOutgoingRtcpPacket( |
495 rtc::ArrayView<const uint8_t> packet) { | 368 rtc::ArrayView<const uint8_t> packet) { |
496 LogRtcpPacket(kOutgoingPacket, packet.data(), packet.size()); | 369 Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(packet)); |
497 } | 370 } |
498 | 371 |
499 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction, | 372 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction, |
500 const uint8_t* packet, | 373 const uint8_t* packet, |
501 size_t length) { | 374 size_t length) { |
502 std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event()); | 375 if (direction == PacketDirection::kIncomingPacket) { |
503 rtcp_event->set_timestamp_us(rtc::TimeMicros()); | 376 LogIncomingRtcpPacket(rtc::ArrayView<const uint8_t>(packet, length)); |
504 rtcp_event->set_type(rtclog::Event::RTCP_EVENT); | 377 } else { |
505 rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket); | 378 RTC_CHECK_EQ(direction, PacketDirection::kOutgoingPacket); |
506 | 379 LogOutgoingRtcpPacket(rtc::ArrayView<const uint8_t>(packet, length)); |
507 rtcp::CommonHeader header; | |
508 const uint8_t* block_begin = packet; | |
509 const uint8_t* packet_end = packet + length; | |
510 RTC_DCHECK(length <= IP_PACKET_SIZE); | |
511 uint8_t buffer[IP_PACKET_SIZE]; | |
512 uint32_t buffer_length = 0; | |
513 while (block_begin < packet_end) { | |
514 if (!header.Parse(block_begin, packet_end - block_begin)) { | |
515 break; // Incorrect message header. | |
516 } | |
517 const uint8_t* next_block = header.NextPacket(); | |
518 uint32_t block_size = next_block - block_begin; | |
519 switch (header.type()) { | |
520 case rtcp::SenderReport::kPacketType: | |
521 case rtcp::ReceiverReport::kPacketType: | |
522 case rtcp::Bye::kPacketType: | |
523 case rtcp::ExtendedJitterReport::kPacketType: | |
524 case rtcp::Rtpfb::kPacketType: | |
525 case rtcp::Psfb::kPacketType: | |
526 case rtcp::ExtendedReports::kPacketType: | |
527 // We log sender reports, receiver reports, bye messages | |
528 // inter-arrival jitter, third-party loss reports, payload-specific | |
529 // feedback and extended reports. | |
530 memcpy(buffer + buffer_length, block_begin, block_size); | |
531 buffer_length += block_size; | |
532 break; | |
533 case rtcp::Sdes::kPacketType: | |
534 case rtcp::App::kPacketType: | |
535 default: | |
536 // We don't log sender descriptions, application defined messages | |
537 // or message blocks of unknown type. | |
538 break; | |
539 } | |
540 | |
541 block_begin += block_size; | |
542 } | 380 } |
543 rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length); | |
544 StoreEvent(std::move(rtcp_event)); | |
545 } | 381 } |
546 | 382 |
547 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) { | 383 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) { |
548 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 384 Log(rtc::MakeUnique<RtcEventAudioPlayout>(ssrc)); |
549 event->set_timestamp_us(rtc::TimeMicros()); | |
550 event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT); | |
551 auto playout_event = event->mutable_audio_playout_event(); | |
552 playout_event->set_local_ssrc(ssrc); | |
553 StoreEvent(std::move(event)); | |
554 } | 385 } |
555 | 386 |
556 void RtcEventLogImpl::LogLossBasedBweUpdate(int32_t bitrate_bps, | 387 void RtcEventLogImpl::LogLossBasedBweUpdate(int32_t bitrate_bps, |
557 uint8_t fraction_loss, | 388 uint8_t fraction_loss, |
558 int32_t total_packets) { | 389 int32_t total_packets) { |
559 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 390 Log(rtc::MakeUnique<RtcEventBweUpdateLossBased>(bitrate_bps, fraction_loss, |
560 event->set_timestamp_us(rtc::TimeMicros()); | 391 total_packets)); |
561 event->set_type(rtclog::Event::LOSS_BASED_BWE_UPDATE); | |
562 auto bwe_event = event->mutable_loss_based_bwe_update(); | |
563 bwe_event->set_bitrate_bps(bitrate_bps); | |
564 bwe_event->set_fraction_loss(fraction_loss); | |
565 bwe_event->set_total_packets(total_packets); | |
566 StoreEvent(std::move(event)); | |
567 } | 392 } |
568 | 393 |
569 void RtcEventLogImpl::LogDelayBasedBweUpdate(int32_t bitrate_bps, | 394 void RtcEventLogImpl::LogDelayBasedBweUpdate(int32_t bitrate_bps, |
570 BandwidthUsage detector_state) { | 395 BandwidthUsage detector_state) { |
571 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 396 Log(rtc::MakeUnique<RtcEventBweUpdateDelayBased>(bitrate_bps, |
572 event->set_timestamp_us(rtc::TimeMicros()); | 397 detector_state)); |
573 event->set_type(rtclog::Event::DELAY_BASED_BWE_UPDATE); | |
574 auto bwe_event = event->mutable_delay_based_bwe_update(); | |
575 bwe_event->set_bitrate_bps(bitrate_bps); | |
576 bwe_event->set_detector_state(ConvertDetectorState(detector_state)); | |
577 StoreEvent(std::move(event)); | |
578 } | 398 } |
579 | 399 |
580 void RtcEventLogImpl::LogAudioNetworkAdaptation( | 400 void RtcEventLogImpl::LogAudioNetworkAdaptation( |
581 const AudioEncoderRuntimeConfig& config) { | 401 const AudioEncoderRuntimeConfig& config) { |
582 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 402 Log(rtc::MakeUnique<RtcEventAudioNetworkAdaptation>( |
583 event->set_timestamp_us(rtc::TimeMicros()); | 403 rtc::MakeUnique<AudioEncoderRuntimeConfig>(config))); |
584 event->set_type(rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT); | |
585 auto audio_network_adaptation = event->mutable_audio_network_adaptation(); | |
586 if (config.bitrate_bps) | |
587 audio_network_adaptation->set_bitrate_bps(*config.bitrate_bps); | |
588 if (config.frame_length_ms) | |
589 audio_network_adaptation->set_frame_length_ms(*config.frame_length_ms); | |
590 if (config.uplink_packet_loss_fraction) { | |
591 audio_network_adaptation->set_uplink_packet_loss_fraction( | |
592 *config.uplink_packet_loss_fraction); | |
593 } | |
594 if (config.enable_fec) | |
595 audio_network_adaptation->set_enable_fec(*config.enable_fec); | |
596 if (config.enable_dtx) | |
597 audio_network_adaptation->set_enable_dtx(*config.enable_dtx); | |
598 if (config.num_channels) | |
599 audio_network_adaptation->set_num_channels(*config.num_channels); | |
600 StoreEvent(std::move(event)); | |
601 } | 404 } |
602 | 405 |
603 void RtcEventLogImpl::LogProbeClusterCreated(int id, | 406 void RtcEventLogImpl::LogProbeClusterCreated(int id, |
604 int bitrate_bps, | 407 int bitrate_bps, |
605 int min_probes, | 408 int min_probes, |
606 int min_bytes) { | 409 int min_bytes) { |
607 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 410 Log(rtc::MakeUnique<RtcEventProbeClusterCreated>(id, bitrate_bps, min_probes, |
608 event->set_timestamp_us(rtc::TimeMicros()); | 411 min_bytes)); |
609 event->set_type(rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT); | |
610 | |
611 auto probe_cluster = event->mutable_probe_cluster(); | |
612 probe_cluster->set_id(id); | |
613 probe_cluster->set_bitrate_bps(bitrate_bps); | |
614 probe_cluster->set_min_packets(min_probes); | |
615 probe_cluster->set_min_bytes(min_bytes); | |
616 StoreEvent(std::move(event)); | |
617 } | 412 } |
618 | 413 |
619 void RtcEventLogImpl::LogProbeResultSuccess(int id, int bitrate_bps) { | 414 void RtcEventLogImpl::LogProbeResultSuccess(int id, int bitrate_bps) { |
620 LogProbeResult(id, rtclog::BweProbeResult::SUCCESS, bitrate_bps); | 415 Log(rtc::MakeUnique<RtcEventProbeResultSuccess>(id, bitrate_bps)); |
621 } | 416 } |
622 | 417 |
623 void RtcEventLogImpl::LogProbeResultFailure(int id, | 418 void RtcEventLogImpl::LogProbeResultFailure(int id, |
624 ProbeFailureReason failure_reason) { | 419 ProbeFailureReason failure_reason) { |
625 rtclog::BweProbeResult::ResultType result = | 420 Log(rtc::MakeUnique<RtcEventProbeResultFailure>(id, failure_reason)); |
626 ConvertProbeResultType(failure_reason); | |
627 LogProbeResult(id, result, -1); | |
628 } | |
629 | |
630 void RtcEventLogImpl::LogProbeResult(int id, | |
631 rtclog::BweProbeResult::ResultType result, | |
632 int bitrate_bps) { | |
633 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | |
634 event->set_timestamp_us(rtc::TimeMicros()); | |
635 event->set_type(rtclog::Event::BWE_PROBE_RESULT_EVENT); | |
636 | |
637 auto probe_result = event->mutable_probe_result(); | |
638 probe_result->set_id(id); | |
639 probe_result->set_result(result); | |
640 if (result == rtclog::BweProbeResult::SUCCESS) | |
641 probe_result->set_bitrate_bps(bitrate_bps); | |
642 StoreEvent(std::move(event)); | |
643 } | 421 } |
644 | 422 |
645 void RtcEventLogImpl::StartLoggingInternal(std::unique_ptr<FileWrapper> file, | 423 void RtcEventLogImpl::StartLoggingInternal(std::unique_ptr<FileWrapper> file, |
646 int64_t max_size_bytes) { | 424 int64_t max_size_bytes) { |
647 LOG(LS_INFO) << "Starting WebRTC event log."; | 425 LOG(LS_INFO) << "Starting WebRTC event log."; |
648 | 426 |
649 max_size_bytes = (max_size_bytes <= 0) | 427 max_size_bytes = (max_size_bytes <= 0) |
650 ? std::numeric_limits<decltype(max_size_bytes)>::max() | 428 ? std::numeric_limits<decltype(max_size_bytes)>::max() |
651 : max_size_bytes; | 429 : max_size_bytes; |
652 auto file_handler = [this, | 430 auto file_handler = [this, |
653 max_size_bytes](std::unique_ptr<FileWrapper> file) { | 431 max_size_bytes](std::unique_ptr<FileWrapper> file) { |
654 RTC_DCHECK_RUN_ON(&task_queue_); | 432 RTC_DCHECK_RUN_ON(&task_queue_); |
655 if (!file_->is_open()) { | 433 if (!file_->is_open()) { |
656 max_size_bytes_ = max_size_bytes; | 434 max_size_bytes_ = max_size_bytes; |
657 file_ = std::move(file); | 435 file_ = std::move(file); |
658 StartLogFile(); | 436 StartLogFile(); |
659 } else { | 437 } else { |
660 // Already started. Ignore message and close file handle. | 438 // Already started. Ignore message and close file handle. |
661 file->CloseFile(); | 439 file->CloseFile(); |
662 } | 440 } |
663 }; | 441 }; |
664 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<FileWrapper>>( | 442 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<FileWrapper>>( |
665 std::move(file), file_handler)); | 443 std::move(file), file_handler)); |
666 } | 444 } |
667 | 445 |
668 void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event> event) { | 446 bool RtcEventLogImpl::AppendEventToString(const RtcEvent& event, |
669 RTC_DCHECK(event); | |
670 | |
671 auto event_handler = [this](std::unique_ptr<rtclog::Event> rtclog_event) { | |
672 RTC_DCHECK_RUN_ON(&task_queue_); | |
673 if (file_->is_open()) { | |
674 LogToFile(std::move(rtclog_event)); | |
675 } else { | |
676 LogToMemory(std::move(rtclog_event)); | |
677 } | |
678 }; | |
679 | |
680 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<rtclog::Event>>( | |
681 std::move(event), event_handler)); | |
682 } | |
683 | |
684 bool RtcEventLogImpl::AppendEventToString(rtclog::Event* event, | |
685 ProtoString* output_string) { | 447 ProtoString* output_string) { |
686 RTC_DCHECK_RUN_ON(&task_queue_); | 448 RTC_DCHECK_RUN_ON(&task_queue_); |
687 | 449 |
688 // Even though we're only serializing a single event during this call, what | 450 std::string encoded_event = event_encoder_->Encode(event); |
689 // we intend to get is a list of events, with a tag and length preceding | |
690 // each actual event. To produce that, we serialize a list of a single event. | |
691 // If we later serialize additional events, the resulting ProtoString will | |
692 // be a proper concatenation of all those events. | |
693 | |
694 rtclog::EventStream event_stream; | |
695 event_stream.add_stream(); | |
696 | |
697 // As a tweak, we swap the new event into the event-stream, write that to | |
698 // file, then swap back. This saves on some copying. | |
699 rtclog::Event* output_event = event_stream.mutable_stream(0); | |
700 output_event->Swap(event); | |
701 | 451 |
702 bool appended; | 452 bool appended; |
703 size_t potential_new_size = | 453 size_t potential_new_size = |
704 written_bytes_ + output_string->size() + event_stream.ByteSize(); | 454 written_bytes_ + output_string->size() + encoded_event.length(); |
705 if (potential_new_size <= max_size_bytes_) { | 455 if (potential_new_size <= max_size_bytes_) { |
706 event_stream.AppendToString(output_string); | 456 *output_string += encoded_event; |
707 appended = true; | 457 appended = true; |
708 } else { | 458 } else { |
709 appended = false; | 459 appended = false; |
710 } | 460 } |
711 | 461 |
712 // When the function returns, the original Event will be unchanged. | |
713 output_event->Swap(event); | |
714 | |
715 return appended; | 462 return appended; |
716 } | 463 } |
717 | 464 |
718 void RtcEventLogImpl::LogToMemory(std::unique_ptr<rtclog::Event> event) { | 465 void RtcEventLogImpl::LogToMemory(std::unique_ptr<RtcEvent> event) { |
719 RTC_DCHECK_RUN_ON(&task_queue_); | 466 RTC_DCHECK_RUN_ON(&task_queue_); |
720 RTC_DCHECK(!file_->is_open()); | 467 RTC_DCHECK(!file_->is_open()); |
721 | 468 |
722 if (IsConfigEvent(*event.get())) { | 469 if (event->IsConfigEvent()) { |
723 config_history_.push_back(std::move(event)); | 470 config_history_.push_back(std::move(event)); |
724 } else { | 471 } else { |
725 history_.push_back(std::move(event)); | 472 history_.push_back(std::move(event)); |
726 if (history_.size() > kEventsInHistory) { | 473 if (history_.size() > kEventsInHistory) { |
727 history_.pop_front(); | 474 history_.pop_front(); |
728 } | 475 } |
729 } | 476 } |
730 } | 477 } |
731 | 478 |
732 void RtcEventLogImpl::StartLogFile() { | 479 void RtcEventLogImpl::StartLogFile() { |
733 RTC_DCHECK_RUN_ON(&task_queue_); | 480 RTC_DCHECK_RUN_ON(&task_queue_); |
734 RTC_DCHECK(file_->is_open()); | 481 RTC_DCHECK(file_->is_open()); |
735 | 482 |
736 ProtoString output_string; | 483 ProtoString output_string; |
737 | 484 |
738 // Create and serialize the LOG_START event. | 485 // Create and serialize the LOG_START event. |
739 // The timestamp used will correspond to when logging has started. The log | 486 // The timestamp used will correspond to when logging has started. The log |
740 // may contain events earlier than the LOG_START event. (In general, the | 487 // may contain events earlier than the LOG_START event. (In general, the |
741 // timestamps in the log are not monotonic.) | 488 // timestamps in the log are not monotonic.) |
742 rtclog::Event start_event; | 489 bool appended = AppendEventToString(RtcEventLoggingStarted(), &output_string); |
743 start_event.set_timestamp_us(rtc::TimeMicros()); | |
744 start_event.set_type(rtclog::Event::LOG_START); | |
745 bool appended = AppendEventToString(&start_event, &output_string); | |
746 | 490 |
747 // Serialize the config information for all old streams, including streams | 491 // Serialize the config information for all old streams, including streams |
748 // which were already logged to previous files. | 492 // which were already logged to previous files. |
749 for (auto& event : config_history_) { | 493 for (auto& event : config_history_) { |
750 if (!appended) { | 494 if (!appended) { |
751 break; | 495 break; |
752 } | 496 } |
753 appended = AppendEventToString(event.get(), &output_string); | 497 appended = AppendEventToString(*event, &output_string); |
754 } | 498 } |
755 | 499 |
756 // Serialize the events in the event queue. | 500 // Serialize the events in the event queue. |
757 while (appended && !history_.empty()) { | 501 while (appended && !history_.empty()) { |
758 appended = AppendEventToString(history_.front().get(), &output_string); | 502 appended = AppendEventToString(*history_.front(), &output_string); |
759 if (appended) { | 503 if (appended) { |
760 // Known issue - if writing to the file fails, these events will have | 504 // Known issue - if writing to the file fails, these events will have |
761 // been lost. If we try to open a new file, these events will be missing | 505 // been lost. If we try to open a new file, these events will be missing |
762 // from it. | 506 // from it. |
763 history_.pop_front(); | 507 history_.pop_front(); |
764 } | 508 } |
765 } | 509 } |
766 | 510 |
767 // Write to file. | 511 // Write to file. |
768 if (!file_->Write(output_string.data(), output_string.size())) { | 512 if (!file_->Write(output_string.data(), output_string.size())) { |
769 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; | 513 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; |
770 // The current FileWrapper implementation closes the file on error. | 514 // The current FileWrapper implementation closes the file on error. |
771 RTC_DCHECK(!file_->is_open()); | 515 RTC_DCHECK(!file_->is_open()); |
772 return; | 516 return; |
773 } | 517 } |
774 written_bytes_ += output_string.size(); | 518 written_bytes_ += output_string.size(); |
775 | 519 |
776 if (!appended) { | 520 if (!appended) { |
777 RTC_DCHECK(file_->is_open()); | 521 RTC_DCHECK(file_->is_open()); |
778 StopLogFile(rtc::TimeMicros()); | 522 StopLogFile(rtc::TimeMicros()); |
779 } | 523 } |
780 } | 524 } |
781 | 525 |
782 void RtcEventLogImpl::LogToFile(std::unique_ptr<rtclog::Event> event) { | 526 void RtcEventLogImpl::LogToFile(std::unique_ptr<RtcEvent> event) { |
783 RTC_DCHECK_RUN_ON(&task_queue_); | 527 RTC_DCHECK_RUN_ON(&task_queue_); |
784 RTC_DCHECK(file_->is_open()); | 528 RTC_DCHECK(file_->is_open()); |
785 | 529 |
786 ProtoString output_string; | 530 ProtoString output_string; |
787 | 531 |
788 bool appended = AppendEventToString(event.get(), &output_string); | 532 bool appended = AppendEventToString(*event, &output_string); |
789 | 533 |
790 if (IsConfigEvent(*event.get())) { | 534 if (event->IsConfigEvent()) { |
791 config_history_.push_back(std::move(event)); | 535 config_history_.push_back(std::move(event)); |
792 } | 536 } |
793 | 537 |
794 if (!appended) { | 538 if (!appended) { |
795 RTC_DCHECK(file_->is_open()); | 539 RTC_DCHECK(file_->is_open()); |
796 history_.push_back(std::move(event)); | 540 history_.push_back(std::move(event)); |
797 StopLogFile(rtc::TimeMicros()); | 541 StopLogFile(rtc::TimeMicros()); |
798 return; | 542 return; |
799 } | 543 } |
800 | 544 |
801 // Write string to file. | 545 // Write string to file. |
802 if (file_->Write(output_string.data(), output_string.size())) { | 546 if (file_->Write(output_string.data(), output_string.size())) { |
803 written_bytes_ += output_string.size(); | 547 written_bytes_ += output_string.size(); |
804 } else { | 548 } else { |
805 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; | 549 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; |
806 // The current FileWrapper implementation closes the file on error. | 550 // The current FileWrapper implementation closes the file on error. |
807 RTC_DCHECK(!file_->is_open()); | 551 RTC_DCHECK(!file_->is_open()); |
808 } | 552 } |
809 } | 553 } |
810 | 554 |
811 void RtcEventLogImpl::StopLogFile(int64_t stop_time) { | 555 void RtcEventLogImpl::StopLogFile(int64_t stop_time) { |
812 RTC_DCHECK_RUN_ON(&task_queue_); | 556 RTC_DCHECK_RUN_ON(&task_queue_); |
813 RTC_DCHECK(file_->is_open()); | 557 RTC_DCHECK(file_->is_open()); |
814 | 558 |
815 ProtoString output_string; | 559 ProtoString output_string; |
816 | 560 |
817 rtclog::Event end_event; | 561 bool appended = AppendEventToString(RtcEventLoggingStopped(), &output_string); |
818 end_event.set_timestamp_us(stop_time); | |
819 end_event.set_type(rtclog::Event::LOG_END); | |
820 bool appended = AppendEventToString(&end_event, &output_string); | |
821 | 562 |
822 if (appended) { | 563 if (appended) { |
823 if (!file_->Write(output_string.data(), output_string.size())) { | 564 if (!file_->Write(output_string.data(), output_string.size())) { |
824 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; | 565 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; |
825 // The current FileWrapper implementation closes the file on error. | 566 // The current FileWrapper implementation closes the file on error. |
826 RTC_DCHECK(!file_->is_open()); | 567 RTC_DCHECK(!file_->is_open()); |
827 } | 568 } |
828 written_bytes_ += output_string.size(); | 569 written_bytes_ += output_string.size(); |
829 } | 570 } |
830 | 571 |
831 max_size_bytes_ = std::numeric_limits<decltype(max_size_bytes_)>::max(); | 572 max_size_bytes_ = std::numeric_limits<decltype(max_size_bytes_)>::max(); |
832 written_bytes_ = 0; | 573 written_bytes_ = 0; |
833 | 574 |
834 file_->CloseFile(); | 575 file_->CloseFile(); |
835 RTC_DCHECK(!file_->is_open()); | 576 RTC_DCHECK(!file_->is_open()); |
836 } | 577 } |
837 | 578 |
838 #endif // ENABLE_RTC_EVENT_LOG | 579 #endif // ENABLE_RTC_EVENT_LOG |
839 | 580 |
840 // RtcEventLog member functions. | 581 // RtcEventLog member functions. |
841 std::unique_ptr<RtcEventLog> RtcEventLog::Create() { | 582 std::unique_ptr<RtcEventLog> RtcEventLog::Create(EncodingType encoding_type) { |
842 #ifdef ENABLE_RTC_EVENT_LOG | 583 #ifdef ENABLE_RTC_EVENT_LOG |
843 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. | 584 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. |
844 constexpr int kMaxLogCount = 5; | 585 constexpr int kMaxLogCount = 5; |
845 int count = 1 + std::atomic_fetch_add(&rtc_event_log_count, 1); | 586 int count = 1 + std::atomic_fetch_add(&rtc_event_log_count, 1); |
846 if (count > kMaxLogCount) { | 587 if (count > kMaxLogCount) { |
847 LOG(LS_WARNING) << "Denied creation of additional WebRTC event logs. " | 588 LOG(LS_WARNING) << "Denied creation of additional WebRTC event logs. " |
848 << count - 1 << " logs open already."; | 589 << count - 1 << " logs open already."; |
849 std::atomic_fetch_sub(&rtc_event_log_count, 1); | 590 std::atomic_fetch_sub(&rtc_event_log_count, 1); |
850 return CreateNull(); | 591 return CreateNull(); |
851 } | 592 } |
852 return rtc::MakeUnique<RtcEventLogImpl>(); | 593 auto encoder = CreateEncoder(encoding_type); |
| 594 return rtc::MakeUnique<RtcEventLogImpl>(std::move(encoder)); |
853 #else | 595 #else |
854 return CreateNull(); | 596 return CreateNull(); |
855 #endif // ENABLE_RTC_EVENT_LOG | 597 #endif // ENABLE_RTC_EVENT_LOG |
856 } | 598 } |
857 | 599 |
858 std::unique_ptr<RtcEventLog> RtcEventLog::CreateNull() { | 600 std::unique_ptr<RtcEventLog> RtcEventLog::CreateNull() { |
859 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl()); | 601 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl()); |
860 } | 602 } |
861 | 603 |
862 } // namespace webrtc | 604 } // namespace webrtc |
OLD | NEW |