1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_ 12 #define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_ 13 14 // To enable BWE logging, run this command from trunk/ : 15 // build/gyp_chromium --depth=. webrtc/modules/modules.gyp 16 // -Denable_bwe_test_logging=1 17 #ifndef BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 18 #define BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 0 19 #endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 20 21 // BWE logging allows you to insert dynamically named log/plot points in the 22 // call tree. E.g. the function: 23 // void f1() { 24 // BWE_TEST_LOGGING_TIME(clock_->TimeInMilliseconds()); 25 // BWE_TEST_LOGGING_CONTEXT("stream"); 26 // for (uint32_t i=0; i<4; ++i) { 27 // BWE_TEST_LOGGING_ENABLE(i & 1); 28 // BWE_TEST_LOGGING_CONTEXT(i); 29 // BWE_TEST_LOGGING_LOG1("weight", "%f tonnes", weights_[i]); 30 // for (float j=0.0f; j<1.0; j+=0.4f) { 31 // BWE_TEST_LOGGING_PLOT(0, "bps", -1, j); 32 // } 33 // } 34 // } 35 // 36 // Might produce the output: 37 // stream_00000001_weight 13.000000 tonnes 38 // PLOT stream_00000001_bps 1.000000 0.000000 39 // PLOT stream_00000001_bps 1.000000 0.400000 40 // PLOT stream_00000001_bps 1.000000 0.800000 41 // stream_00000003_weight 39.000000 tonnes 42 // PLOT stream_00000003_bps 1.000000 0.000000 43 // PLOT stream_00000003_bps 1.000000 0.400000 44 // PLOT stream_00000003_bps 1.000000 0.800000 45 // 46 // Log *contexts* are names concatenated with '_' between them, with the name 47 // of the logged/plotted string/value last. Plot *time* is inherited down the 48 // tree. A branch is enabled by default but can be *disabled* to reduce output. 49 // The difference between the RTC_LOG and PLOT macros is that PLOT prefixes the 50 // line so it can be easily filtered, plus it outputs the current time. 51 52 #if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE) 53 54 // Set a thread-global base logging context. This name will be prepended to all 55 // hierarchical contexts. 56 // `name` is a char*, std::string or uint32_t to name the context. 57 #define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name) 58 59 // Thread-globally allow/disallow logging. 60 // `enable` is expected to be a bool. 61 #define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled) 62 63 // Insert a (hierarchical) logging context. 64 // `name` is a char*, std::string or uint32_t to name the context. 65 #define BWE_TEST_LOGGING_CONTEXT(name) 66 67 // Allow/disallow logging down the call tree from this point. Logging must be 68 // enabled all the way to the root of the call tree to take place. 69 // `enable` is expected to be a bool. 70 #define BWE_TEST_LOGGING_ENABLE(enabled) 71 72 // Set current time (only affects PLOT output). Down the call tree, the latest 73 // time set always takes precedence. 74 // `time` is an int64_t time in ms, or -1 to inherit time from previous context. 75 #define BWE_TEST_LOGGING_TIME(time) 76 77 // Print to stdout, e.g.: 78 // Context1_Context2_Name printf-formated-string 79 // `name` is a char*, std::string or uint32_t to name the log line. 80 // `format` is a printf format string. 81 // |_1...| are arguments for printf. 82 #define BWE_TEST_LOGGING_LOG1(name, format, _1) 83 #define BWE_TEST_LOGGING_LOG2(name, format, _1, _2) 84 #define BWE_TEST_LOGGING_LOG3(name, format, _1, _2, _3) 85 #define BWE_TEST_LOGGING_LOG4(name, format, _1, _2, _3, _4) 86 #define BWE_TEST_LOGGING_LOG5(name, format, _1, _2, _3, _4, _5) 87 88 // Print to stdout in tab-separated format suitable for plotting, e.g.: 89 // PLOT figure Context1_Context2_Name time value 90 // `figure` is a figure id. Different figures are plotted in different windows. 91 // `name` is a char*, std::string or uint32_t to name the plotted value. 92 // `time` is an int64_t time in ms, or -1 to inherit time from previous context. 93 // `value` is a double precision float to be plotted. 94 // `ssrc` identifies the source of a stream 95 // `alg_name` is an optional argument, a string 96 #define BWE_TEST_LOGGING_PLOT(figure, name, time, value) 97 #define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) 98 #define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) 99 #define BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(figure, name, time, value, \ 100 ssrc, alg_name) 101 102 // Print to stdout in tab-separated format suitable for plotting, e.g.: 103 // BAR figure Context1_Context2_Name x_left width value 104 // `figure` is a figure id. Different figures are plotted in different windows. 105 // `name` is a char*, std::string or uint32_t to name the plotted value. 106 // `value` is a double precision float to be plotted. 107 // `ylow` and `yhigh` are double precision float for the error line. 108 // `title` is a string and refers to the error label. 109 // `ymax` is a double precision float for the limit horizontal line. 110 // `limit_title` is a string and refers to the limit label. 111 #define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id) 112 #define BWE_TEST_LOGGING_ERRORBAR(figure, name, value, ylow, yhigh, \ 113 error_title, flow_id) 114 #define BWE_TEST_LOGGING_LIMITERRORBAR( \ 115 figure, name, value, ylow, yhigh, error_title, ymax, limit_title, flow_id) 116 117 #define BWE_TEST_LOGGING_BASELINEBAR(figure, name, value, flow_id) 118 119 // `num_flows` is an integer refering to the number of RMCAT flows in the 120 // scenario. 121 // Define `x_label` and `y_label` for plots. 122 #define BWE_TEST_LOGGING_LABEL(figure, x_label, y_label, num_flows) 123 124 #else // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 125 126 #include <map> 127 #include <memory> 128 #include <stack> 129 #include <string> 130 131 #include "rtc_base/synchronization/mutex.h" 132 133 #define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name) \ 134 do { \ 135 webrtc::testing::bwe::Logging::GetInstance()->SetGlobalContext(name); \ 136 } while (0) 137 138 #define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled) \ 139 do { \ 140 webrtc::testing::bwe::Logging::GetInstance()->SetGlobalEnable(enabled); \ 141 } while (0) 142 143 #define __BWE_TEST_LOGGING_CONTEXT_NAME(ctx, line) ctx##line 144 #define __BWE_TEST_LOGGING_CONTEXT_DECLARE(ctx, line, name, time, enabled) \ 145 webrtc::testing::bwe::Logging::Context __BWE_TEST_LOGGING_CONTEXT_NAME( \ 146 ctx, line)(name, time, enabled) 147 148 #define BWE_TEST_LOGGING_CONTEXT(name) \ 149 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, name, -1, true) 150 #define BWE_TEST_LOGGING_ENABLE(enabled) \ 151 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, "", -1, \ 152 static_cast<bool>(enabled)) 153 #define BWE_TEST_LOGGING_TIME(time) \ 154 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, "", \ 155 static_cast<int64_t>(time), true) 156 157 #define BWE_TEST_LOGGING_LOG1(name, format, _1) \ 158 do { \ 159 BWE_TEST_LOGGING_CONTEXT(name); \ 160 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1); \ 161 } while (0) 162 #define BWE_TEST_LOGGING_LOG2(name, format, _1, _2) \ 163 do { \ 164 BWE_TEST_LOGGING_CONTEXT(name); \ 165 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2); \ 166 } while (0) 167 #define BWE_TEST_LOGGING_LOG3(name, format, _1, _2, _3) \ 168 do { \ 169 BWE_TEST_LOGGING_CONTEXT(name); \ 170 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3); \ 171 } while (0) 172 #define BWE_TEST_LOGGING_LOG4(name, format, _1, _2, _3, _4) \ 173 do { \ 174 BWE_TEST_LOGGING_CONTEXT(name); \ 175 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3, _4); \ 176 } while (0) 177 #define BWE_TEST_LOGGING_LOG5(name, format, _1, _2, _3, _4, _5) \ 178 do { \ 179 BWE_TEST_LOGGING_CONTEXT(name); \ 180 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3, _4, \ 181 _5); \ 182 } while (0) 183 184 #define BWE_TEST_LOGGING_PLOT(figure, name, time, value) \ 185 do { \ 186 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 187 static_cast<int64_t>(time), true); \ 188 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value); \ 189 } while (0) 190 191 #define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) \ 192 do { \ 193 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 194 static_cast<int64_t>(time), true); \ 195 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ 196 alg_name); \ 197 } while (0) 198 199 #define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) \ 200 do { \ 201 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 202 static_cast<int64_t>(time), true); \ 203 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ 204 ssrc); \ 205 } while (0) 206 207 #define BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(figure, name, time, value, \ 208 ssrc, alg_name) \ 209 do { \ 210 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 211 static_cast<int64_t>(time), true); \ 212 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ 213 ssrc, alg_name); \ 214 } while (0) 215 216 #define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id) \ 217 do { \ 218 BWE_TEST_LOGGING_CONTEXT(name); \ 219 webrtc::testing::bwe::Logging::GetInstance()->PlotBar(figure, name, value, \ 220 flow_id); \ 221 } while (0) 222 223 #define BWE_TEST_LOGGING_BASELINEBAR(figure, name, value, flow_id) \ 224 do { \ 225 BWE_TEST_LOGGING_CONTEXT(name); \ 226 webrtc::testing::bwe::Logging::GetInstance()->PlotBaselineBar( \ 227 figure, name, value, flow_id); \ 228 } while (0) 229 230 #define BWE_TEST_LOGGING_ERRORBAR(figure, name, value, ylow, yhigh, title, \ 231 flow_id) \ 232 do { \ 233 BWE_TEST_LOGGING_CONTEXT(name); \ 234 webrtc::testing::bwe::Logging::GetInstance()->PlotErrorBar( \ 235 figure, name, value, ylow, yhigh, title, flow_id); \ 236 } while (0) 237 238 #define BWE_TEST_LOGGING_LIMITERRORBAR( \ 239 figure, name, value, ylow, yhigh, error_title, ymax, limit_title, flow_id) \ 240 do { \ 241 BWE_TEST_LOGGING_CONTEXT(name); \ 242 webrtc::testing::bwe::Logging::GetInstance()->PlotLimitErrorBar( \ 243 figure, name, value, ylow, yhigh, error_title, ymax, limit_title, \ 244 flow_id); \ 245 } while (0) 246 247 #define BWE_TEST_LOGGING_LABEL(figure, title, y_label, num_flows) \ 248 do { \ 249 BWE_TEST_LOGGING_CONTEXT(title); \ 250 webrtc::testing::bwe::Logging::GetInstance()->PlotLabel( \ 251 figure, title, y_label, num_flows); \ 252 } while (0) 253 254 namespace webrtc { 255 namespace testing { 256 namespace bwe { 257 258 class Logging { 259 public: 260 class Context { 261 public: 262 Context(uint32_t name, int64_t timestamp_ms, bool enabled); 263 Context(const std::string& name, int64_t timestamp_ms, bool enabled); 264 Context(const char* name, int64_t timestamp_ms, bool enabled); 265 266 Context() = delete; 267 Context(const Context&) = delete; 268 Context& operator=(const Context&) = delete; 269 ~Context(); 270 }; 271 272 static Logging* GetInstance(); 273 274 void SetGlobalContext(uint32_t name); 275 void SetGlobalContext(const std::string& name); 276 void SetGlobalContext(const char* name); 277 void SetGlobalEnable(bool enabled); 278 279 #if defined(__GNUC__) 280 // Note: Implicit `this` argument counts as the first argument. 281 __attribute__((__format__(__printf__, 2, 3))) 282 #endif 283 void 284 Log(const char format[], ...); 285 void Plot(int figure, const std::string& name, double value); 286 void Plot(int figure, 287 const std::string& name, 288 double value, 289 const std::string& alg_name); 290 void Plot(int figure, const std::string& name, double value, uint32_t ssrc); 291 void Plot(int figure, 292 const std::string& name, 293 double value, 294 uint32_t ssrc, 295 const std::string& alg_name); 296 void PlotBar(int figure, const std::string& name, double value, int flow_id); 297 void PlotBaselineBar(int figure, 298 const std::string& name, 299 double value, 300 int flow_id); 301 void PlotErrorBar(int figure, 302 const std::string& name, 303 double value, 304 double ylow, 305 double yhigh, 306 const std::string& error_title, 307 int flow_id); 308 309 void PlotLimitErrorBar(int figure, 310 const std::string& name, 311 double value, 312 double ylow, 313 double yhigh, 314 const std::string& error_title, 315 double ymax, 316 const std::string& limit_title, 317 int flow_id); 318 void PlotLabel(int figure, 319 const std::string& title, 320 const std::string& y_label, 321 int num_flows); 322 323 private: 324 struct State { 325 State(); 326 State(const std::string& new_tag, int64_t timestamp_ms, bool enabled); 327 void MergePrevious(const State& previous); 328 329 std::string tag; 330 int64_t timestamp_ms; 331 bool enabled; 332 }; 333 struct ThreadState { 334 ThreadState(); 335 ~ThreadState(); 336 State global_state; 337 std::stack<State> stack; 338 }; 339 typedef std::map<uint32_t, ThreadState> ThreadMap; 340 341 Logging(); 342 ~Logging(); 343 344 Logging(const Logging&) = delete; 345 Logging& operator=(const Logging&) = delete; 346 347 void PushState(const std::string& append_to_tag, 348 int64_t timestamp_ms, 349 bool enabled); 350 void PopState(); 351 352 Mutex mutex_; 353 ThreadMap thread_map_; 354 }; 355 } // namespace bwe 356 } // namespace testing 357 } // namespace webrtc 358 359 #endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 360 #endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_ 361