aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h
blob: cc7807ba8aaac36f9149426e7dda023185fadf5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_

// To enable BWE logging, run this command from trunk/ :
// build/gyp_chromium --depth=. webrtc/modules/modules.gyp
//   -Denable_bwe_test_logging=1
#ifndef BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
#define BWE_TEST_LOGGING_COMPILE_TIME_ENABLE 0
#endif  // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE

// BWE logging allows you to insert dynamically named log/plot points in the
// call tree. E.g. the function:
//  void f1() {
//    BWE_TEST_LOGGING_TIME(clock_->TimeInMilliseconds());
//    BWE_TEST_LOGGING_CONTEXT("stream");
//    for (uint32_t i=0; i<4; ++i) {
//      BWE_TEST_LOGGING_ENABLE(i & 1);
//      BWE_TEST_LOGGING_CONTEXT(i);
//      BWE_TEST_LOGGING_LOG1("weight", "%f tonnes", weights_[i]);
//      for (float j=0.0f; j<1.0; j+=0.4f) {
//        BWE_TEST_LOGGING_PLOT(0, "bps", -1, j);
//      }
//    }
//  }
//
// Might produce the output:
//   stream_00000001_weight 13.000000 tonnes
//   PLOT  stream_00000001_bps  1.000000  0.000000
//   PLOT  stream_00000001_bps  1.000000  0.400000
//   PLOT  stream_00000001_bps  1.000000  0.800000
//   stream_00000003_weight 39.000000 tonnes
//   PLOT  stream_00000003_bps  1.000000  0.000000
//   PLOT  stream_00000003_bps  1.000000  0.400000
//   PLOT  stream_00000003_bps  1.000000  0.800000
//
// Log *contexts* are names concatenated with '_' between them, with the name
// of the logged/plotted string/value last. Plot *time* is inherited down the
// tree. A branch is enabled by default but can be *disabled* to reduce output.
// The difference between the LOG and PLOT macros is that PLOT prefixes the line
// so it can be easily filtered, plus it outputs the current time.

#if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)

// Set a thread-global base logging context. This name will be prepended to all
// hierarchical contexts.
// |name| is a char*, std::string or uint32_t to name the context.
#define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name)

// Thread-globally allow/disallow logging.
// |enable| is expected to be a bool.
#define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled)

// Insert a (hierarchical) logging context.
// |name| is a char*, std::string or uint32_t to name the context.
#define BWE_TEST_LOGGING_CONTEXT(name)

// Allow/disallow logging down the call tree from this point. Logging must be
// enabled all the way to the root of the call tree to take place.
// |enable| is expected to be a bool.
#define BWE_TEST_LOGGING_ENABLE(enabled)

// Set current time (only affects PLOT output). Down the call tree, the latest
// time set always takes precedence.
// |time| is an int64_t time in ms, or -1 to inherit time from previous context.
#define BWE_TEST_LOGGING_TIME(time)

// Print to stdout, e.g.:
//   Context1_Context2_Name  printf-formated-string
// |name| is a char*, std::string or uint32_t to name the log line.
// |format| is a printf format string.
// |_1...| are arguments for printf.
#define BWE_TEST_LOGGING_LOG1(name, format, _1)
#define BWE_TEST_LOGGING_LOG2(name, format, _1, _2)
#define BWE_TEST_LOGGING_LOG3(name, format, _1, _2, _3)
#define BWE_TEST_LOGGING_LOG4(name, format, _1, _2, _3, _4)
#define BWE_TEST_LOGGING_LOG5(name, format, _1, _2, _3, _4, _5)

// Print to stdout in tab-separated format suitable for plotting, e.g.:
//   PLOT figure Context1_Context2_Name  time  value
// |figure| is a figure id. Different figures are plotted in different windows.
// |name| is a char*, std::string or uint32_t to name the plotted value.
// |time| is an int64_t time in ms, or -1 to inherit time from previous context.
// |value| is a double precision float to be plotted.
// |alg_name| is an optional argument, a string
#define BWE_TEST_LOGGING_PLOT(figure, name, time, value)
#define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name)

// Print to stdout in tab-separated format suitable for plotting, e.g.:
//   BAR figure Context1_Context2_Name  x_left  width  value
// |figure| is a figure id. Different figures are plotted in different windows.
// |name| is a char*, std::string or uint32_t to name the plotted value.
// |value| is a double precision float to be plotted.
// |ylow| and |yhigh| are double precision float for the error line.
// |title| is a string and refers to the error label.
// |ymax| is a double precision float for the limit horizontal line.
// |limit_title| is a string and refers to the limit label.
#define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id)
#define BWE_TEST_LOGGING_ERRORBAR(figure, name, value, ylow, yhigh, \
                                  error_title, flow_id)
#define BWE_TEST_LOGGING_LIMITERRORBAR( \
    figure, name, value, ylow, yhigh, error_title, ymax, limit_title, flow_id)

#define BWE_TEST_LOGGING_BASELINEBAR(figure, name, value, flow_id)

// |num_flows| is an integer refering to the number of RMCAT flows in the
// scenario.
// Define |x_label| and |y_label| for plots.
#define BWE_TEST_LOGGING_LABEL(figure, x_label, y_label, num_flows)

#else  // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE

#include <map>
#include <stack>
#include <string>

#include "webrtc/base/constructormagic.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_types.h"

#define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name) \
    do { \
      webrtc::testing::bwe::Logging::GetInstance()->SetGlobalContext(name); \
    } while (0)

#define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled) \
    do { \
      webrtc::testing::bwe::Logging::GetInstance()->SetGlobalEnable(enabled); \
    } while (0)

#define __BWE_TEST_LOGGING_CONTEXT_NAME(ctx, line) ctx ## line
#define __BWE_TEST_LOGGING_CONTEXT_DECLARE(ctx, line, name, time, enabled) \
    webrtc::testing::bwe::Logging::Context \
        __BWE_TEST_LOGGING_CONTEXT_NAME(ctx, line)(name, time, enabled)

#define BWE_TEST_LOGGING_CONTEXT(name) \
    __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, name, -1, true)
#define BWE_TEST_LOGGING_ENABLE(enabled) \
    __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, "", -1, \
                                       static_cast<bool>(enabled))
#define BWE_TEST_LOGGING_TIME(time) \
    __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __LINE__, "", \
                                       static_cast<int64_t>(time), true)

#define BWE_TEST_LOGGING_LOG1(name, format, _1) \
    do { \
      BWE_TEST_LOGGING_CONTEXT(name); \
      webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1); \
    } while (0)
#define BWE_TEST_LOGGING_LOG2(name, format, _1, _2) \
    do { \
      BWE_TEST_LOGGING_CONTEXT(name); \
      webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2); \
    } while (0)
#define BWE_TEST_LOGGING_LOG3(name, format, _1, _2, _3) \
    do { \
      BWE_TEST_LOGGING_CONTEXT(name); \
      webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3); \
    } while (0)
#define BWE_TEST_LOGGING_LOG4(name, format, _1, _2, _3, _4) \
    do { \
      BWE_TEST_LOGGING_CONTEXT(name); \
      webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3, \
                                                        _4); \
    } while (0)
#define BWE_TEST_LOGGING_LOG5(name, format, _1, _2, _3, _4, _5) \
    do {\
      BWE_TEST_LOGGING_CONTEXT(name); \
      webrtc::testing::bwe::Logging::GetInstance()->Log(format, _1, _2, _3, \
                                                        _4, _5); \
    } while (0)

#define BWE_TEST_LOGGING_PLOT(figure, name, time, value)                  \
  do {                                                                    \
    __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name,        \
                                       static_cast<int64_t>(time), true); \
    webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value);    \
  } while (0)

#define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) \
  do {                                                                       \
    __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name,           \
                                       static_cast<int64_t>(time), true);    \
    webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value,        \
                                                       alg_name);            \
  } while (0)

#define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id)                     \
  do {                                                                         \
    BWE_TEST_LOGGING_CONTEXT(name);                                            \
    webrtc::testing::bwe::Logging::GetInstance()->PlotBar(figure, name, value, \
                                                          flow_id);            \
  } while (0)

#define BWE_TEST_LOGGING_BASELINEBAR(figure, name, value, flow_id) \
  do {                                                             \
    BWE_TEST_LOGGING_CONTEXT(name);                                \
    webrtc::testing::bwe::Logging::GetInstance()->PlotBaselineBar( \
        figure, name, value, flow_id);                             \
  } while (0)

#define BWE_TEST_LOGGING_ERRORBAR(figure, name, value, ylow, yhigh, title, \
                                  flow_id)                                 \
  do {                                                                     \
    BWE_TEST_LOGGING_CONTEXT(name);                                        \
    webrtc::testing::bwe::Logging::GetInstance()->PlotErrorBar(            \
        figure, name, value, ylow, yhigh, title, flow_id);                 \
  } while (0)

#define BWE_TEST_LOGGING_LIMITERRORBAR(                                        \
    figure, name, value, ylow, yhigh, error_title, ymax, limit_title, flow_id) \
  do {                                                                         \
    BWE_TEST_LOGGING_CONTEXT(name);                                            \
    webrtc::testing::bwe::Logging::GetInstance()->PlotLimitErrorBar(           \
        figure, name, value, ylow, yhigh, error_title, ymax, limit_title,      \
        flow_id);                                                              \
  } while (0)

#define BWE_TEST_LOGGING_LABEL(figure, title, y_label, num_flows) \
  do {                                                            \
    BWE_TEST_LOGGING_CONTEXT(title);                              \
    webrtc::testing::bwe::Logging::GetInstance()->PlotLabel(      \
        figure, title, y_label, num_flows);                       \
  } while (0)

namespace webrtc {

class CriticalSectionWrapper;

namespace testing {
namespace bwe {

class Logging {
 public:
  class Context {
   public:
    Context(uint32_t name, int64_t timestamp_ms, bool enabled);
    Context(const std::string& name, int64_t timestamp_ms, bool enabled);
    Context(const char* name, int64_t timestamp_ms, bool enabled);
    ~Context();
   private:
    RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Context);
  };

  static Logging* GetInstance();

  void SetGlobalContext(uint32_t name);
  void SetGlobalContext(const std::string& name);
  void SetGlobalContext(const char* name);
  void SetGlobalEnable(bool enabled);

  void Log(const char format[], ...);
  void Plot(int figure, double value);
  void Plot(int figure, double value, const std::string& alg_name);
  void PlotBar(int figure, const std::string& name, double value, int flow_id);
  void PlotBaselineBar(int figure,
                       const std::string& name,
                       double value,
                       int flow_id);
  void PlotErrorBar(int figure,
                    const std::string& name,
                    double value,
                    double ylow,
                    double yhigh,
                    const std::string& error_title,
                    int flow_id);

  void PlotLimitErrorBar(int figure,
                         const std::string& name,
                         double value,
                         double ylow,
                         double yhigh,
                         const std::string& error_title,
                         double ymax,
                         const std::string& limit_title,
                         int flow_id);
  void PlotLabel(int figure,
                 const std::string& title,
                 const std::string& y_label,
                 int num_flows);

 private:
  struct State {
    State();
    State(const std::string& new_tag, int64_t timestamp_ms, bool enabled);
    void MergePrevious(const State& previous);

    std::string tag;
    int64_t timestamp_ms;
    bool enabled;
  };
  struct ThreadState {
    State global_state;
    std::stack<State> stack;
  };
  typedef std::map<uint32_t, ThreadState> ThreadMap;

  Logging();
  void PushState(const std::string& append_to_tag, int64_t timestamp_ms,
                 bool enabled);
  void PopState();

  static Logging g_Logging;
  rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
  ThreadMap thread_map_;

  RTC_DISALLOW_COPY_AND_ASSIGN(Logging);
};
}  // namespace bwe
}  // namespace testing
}  // namespace webrtc

#endif  // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
#endif  // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_LOGGING_H_