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/constructor_magic.h" 132 #include "rtc_base/synchronization/mutex.h" 133 134 #define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name) \ 135 do { \ 136 webrtc::testing::bwe::Logging::GetInstance()->SetGlobalContext(name); \ 137 } while (0) 138 139 #define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled) \ 140 do { \ 141 webrtc::testing::bwe::Logging::GetInstance()->SetGlobalEnable(enabled); \ 142 } while (0) 143 144 #define __BWE_TEST_LOGGING_CONTEXT_NAME(ctx, line) ctx##line 145 #define __BWE_TEST_LOGGING_CONTEXT_DECLARE(ctx, line, name, time, enabled) \ 146 webrtc::testing::bwe::Logging::Context __BWE_TEST_LOGGING_CONTEXT_NAME( \ 147 ctx, line)(name, time, enabled) 148 149 #define BWE_TEST_LOGGING_CONTEXT(name) \ 150 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, name, -1, true) 151 #define BWE_TEST_LOGGING_ENABLE(enabled) \ 152 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, "", -1, \ 153 static_cast<bool>(enabled)) 154 #define BWE_TEST_LOGGING_TIME(time) \ 155 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, "", \ 156 static_cast<int64_t>(time), true) 157 158 #define BWE_TEST_LOGGING_LOG1(name, format, _1) \ 159 do { \ 160 BWE_TEST_LOGGING_CONTEXT(name); \ 161 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1); \ 162 } while (0) 163 #define BWE_TEST_LOGGING_LOG2(name, format, _1, _2) \ 164 do { \ 165 BWE_TEST_LOGGING_CONTEXT(name); \ 166 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2); \ 167 } while (0) 168 #define BWE_TEST_LOGGING_LOG3(name, format, _1, _2, _3) \ 169 do { \ 170 BWE_TEST_LOGGING_CONTEXT(name); \ 171 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3); \ 172 } while (0) 173 #define BWE_TEST_LOGGING_LOG4(name, format, _1, _2, _3, _4) \ 174 do { \ 175 BWE_TEST_LOGGING_CONTEXT(name); \ 176 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3, _4); \ 177 } while (0) 178 #define BWE_TEST_LOGGING_LOG5(name, format, _1, _2, _3, _4, _5) \ 179 do { \ 180 BWE_TEST_LOGGING_CONTEXT(name); \ 181 webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3, _4, \ 182 _5); \ 183 } while (0) 184 185 #define BWE_TEST_LOGGING_PLOT(figure, name, time, value) \ 186 do { \ 187 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 188 static_cast<int64_t>(time), true); \ 189 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value); \ 190 } while (0) 191 192 #define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) \ 193 do { \ 194 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 195 static_cast<int64_t>(time), true); \ 196 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ 197 alg_name); \ 198 } while (0) 199 200 #define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) \ 201 do { \ 202 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 203 static_cast<int64_t>(time), true); \ 204 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ 205 ssrc); \ 206 } while (0) 207 208 #define BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(figure, name, time, value, \ 209 ssrc, alg_name) \ 210 do { \ 211 __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ 212 static_cast<int64_t>(time), true); \ 213 webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ 214 ssrc, alg_name); \ 215 } while (0) 216 217 #define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id) \ 218 do { \ 219 BWE_TEST_LOGGING_CONTEXT(name); \ 220 webrtc::testing::bwe::Logging::GetInstance()->PlotBar(figure, name, value, \ 221 flow_id); \ 222 } while (0) 223 224 #define BWE_TEST_LOGGING_BASELINEBAR(figure, name, value, flow_id) \ 225 do { \ 226 BWE_TEST_LOGGING_CONTEXT(name); \ 227 webrtc::testing::bwe::Logging::GetInstance()->PlotBaselineBar( \ 228 figure, name, value, flow_id); \ 229 } while (0) 230 231 #define BWE_TEST_LOGGING_ERRORBAR(figure, name, value, ylow, yhigh, title, \ 232 flow_id) \ 233 do { \ 234 BWE_TEST_LOGGING_CONTEXT(name); \ 235 webrtc::testing::bwe::Logging::GetInstance()->PlotErrorBar( \ 236 figure, name, value, ylow, yhigh, title, flow_id); \ 237 } while (0) 238 239 #define BWE_TEST_LOGGING_LIMITERRORBAR( \ 240 figure, name, value, ylow, yhigh, error_title, ymax, limit_title, flow_id) \ 241 do { \ 242 BWE_TEST_LOGGING_CONTEXT(name); \ 243 webrtc::testing::bwe::Logging::GetInstance()->PlotLimitErrorBar( \ 244 figure, name, value, ylow, yhigh, error_title, ymax, limit_title, \ 245 flow_id); \ 246 } while (0) 247 248 #define BWE_TEST_LOGGING_LABEL(figure, title, y_label, num_flows) \ 249 do { \ 250 BWE_TEST_LOGGING_CONTEXT(title); \ 251 webrtc::testing::bwe::Logging::GetInstance()->PlotLabel( \ 252 figure, title, y_label, num_flows); \ 253 } while (0) 254 255 namespace webrtc { 256 namespace testing { 257 namespace bwe { 258 259 class Logging { 260 public: 261 class Context { 262 public: 263 Context(uint32_t name, int64_t timestamp_ms, bool enabled); 264 Context(const std::string& name, int64_t timestamp_ms, bool enabled); 265 Context(const char* name, int64_t timestamp_ms, bool enabled); 266 ~Context(); 267 268 private: 269 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(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 void PushState(const std::string& append_to_tag, 344 int64_t timestamp_ms, 345 bool enabled); 346 void PopState(); 347 348 Mutex mutex_; 349 ThreadMap thread_map_; 350 351 RTC_DISALLOW_COPY_AND_ASSIGN(Logging); 352 }; 353 } // namespace bwe 354 } // namespace testing 355 } // namespace webrtc 356 357 #endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 358 #endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_ 359