Home | History | Annotate | Download | only in test
      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 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
     12 
     13 #if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
     14 
     15 #include <stdarg.h>
     16 #include <stdio.h>
     17 
     18 #include <algorithm>
     19 #include <sstream>
     20 
     21 #include "webrtc/base/platform_thread.h"
     22 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     23 
     24 namespace webrtc {
     25 namespace testing {
     26 namespace bwe {
     27 
     28 Logging Logging::g_Logging;
     29 
     30 static std::string ToString(uint32_t v) {
     31   std::stringstream ss;
     32   ss << v;
     33   return ss.str();
     34 }
     35 
     36 Logging::Context::Context(uint32_t name, int64_t timestamp_ms, bool enabled) {
     37   Logging::GetInstance()->PushState(ToString(name), timestamp_ms, enabled);
     38 }
     39 
     40 Logging::Context::Context(const std::string& name, int64_t timestamp_ms,
     41                           bool enabled) {
     42   Logging::GetInstance()->PushState(name, timestamp_ms, enabled);
     43 }
     44 
     45 Logging::Context::Context(const char* name, int64_t timestamp_ms,
     46                           bool enabled) {
     47   Logging::GetInstance()->PushState(name, timestamp_ms, enabled);
     48 }
     49 
     50 Logging::Context::~Context() {
     51   Logging::GetInstance()->PopState();
     52 }
     53 
     54 Logging* Logging::GetInstance() {
     55   return &g_Logging;
     56 }
     57 
     58 void Logging::SetGlobalContext(uint32_t name) {
     59   CriticalSectionScoped cs(crit_sect_.get());
     60   thread_map_[rtc::CurrentThreadId()].global_state.tag = ToString(name);
     61 }
     62 
     63 void Logging::SetGlobalContext(const std::string& name) {
     64   CriticalSectionScoped cs(crit_sect_.get());
     65   thread_map_[rtc::CurrentThreadId()].global_state.tag = name;
     66 }
     67 
     68 void Logging::SetGlobalContext(const char* name) {
     69   CriticalSectionScoped cs(crit_sect_.get());
     70   thread_map_[rtc::CurrentThreadId()].global_state.tag = name;
     71 }
     72 
     73 void Logging::SetGlobalEnable(bool enabled) {
     74   CriticalSectionScoped cs(crit_sect_.get());
     75   thread_map_[rtc::CurrentThreadId()].global_state.enabled = enabled;
     76 }
     77 
     78 void Logging::Log(const char format[], ...) {
     79   CriticalSectionScoped cs(crit_sect_.get());
     80   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
     81   assert(it != thread_map_.end());
     82   const State& state = it->second.stack.top();
     83   if (state.enabled) {
     84     printf("%s\t", state.tag.c_str());
     85     va_list args;
     86     va_start(args, format);
     87     vprintf(format, args);
     88     va_end(args);
     89     printf("\n");
     90   }
     91 }
     92 
     93 void Logging::Plot(int figure, double value) {
     94   Plot(figure, value, "-");
     95 }
     96 
     97 void Logging::Plot(int figure, double value, const std::string& alg_name) {
     98   CriticalSectionScoped cs(crit_sect_.get());
     99   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    100   assert(it != thread_map_.end());
    101   const State& state = it->second.stack.top();
    102   std::string label = state.tag + '@' + alg_name;
    103   std::string prefix("Available");
    104   if (alg_name.compare(0, prefix.length(), prefix) == 0) {
    105     std::string receiver("Receiver");
    106     size_t start_pos = label.find(receiver);
    107     if (start_pos != std::string::npos) {
    108       label.replace(start_pos, receiver.length(), "Sender");
    109     }
    110   }
    111   if (state.enabled) {
    112     printf("PLOT\t%d\t%s\t%f\t%f\n", figure, label.c_str(),
    113            state.timestamp_ms * 0.001, value);
    114   }
    115 }
    116 
    117 void Logging::PlotBar(int figure,
    118                       const std::string& name,
    119                       double value,
    120                       int flow_id) {
    121   CriticalSectionScoped cs(crit_sect_.get());
    122   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    123   assert(it != thread_map_.end());
    124   const State& state = it->second.stack.top();
    125   if (state.enabled) {
    126     printf("BAR\t%d\t%s_%d\t%f\n", figure, name.c_str(), flow_id, value);
    127   }
    128 }
    129 
    130 void Logging::PlotBaselineBar(int figure,
    131                               const std::string& name,
    132                               double value,
    133                               int flow_id) {
    134   CriticalSectionScoped cs(crit_sect_.get());
    135   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    136   assert(it != thread_map_.end());
    137   const State& state = it->second.stack.top();
    138   if (state.enabled) {
    139     printf("BASELINE\t%d\t%s_%d\t%f\n", figure, name.c_str(), flow_id, value);
    140   }
    141 }
    142 
    143 void Logging::PlotErrorBar(int figure,
    144                            const std::string& name,
    145                            double value,
    146                            double ylow,
    147                            double yhigh,
    148                            const std::string& error_title,
    149                            int flow_id) {
    150   CriticalSectionScoped cs(crit_sect_.get());
    151   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    152   assert(it != thread_map_.end());
    153   const State& state = it->second.stack.top();
    154   if (state.enabled) {
    155     printf("ERRORBAR\t%d\t%s_%d\t%f\t%f\t%f\t%s\n", figure, name.c_str(),
    156            flow_id, value, ylow, yhigh, error_title.c_str());
    157   }
    158 }
    159 
    160 void Logging::PlotLimitErrorBar(int figure,
    161                                 const std::string& name,
    162                                 double value,
    163                                 double ylow,
    164                                 double yhigh,
    165                                 const std::string& error_title,
    166                                 double ymax,
    167                                 const std::string& limit_title,
    168                                 int flow_id) {
    169   CriticalSectionScoped cs(crit_sect_.get());
    170   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    171   assert(it != thread_map_.end());
    172   const State& state = it->second.stack.top();
    173   if (state.enabled) {
    174     printf("LIMITERRORBAR\t%d\t%s_%d\t%f\t%f\t%f\t%s\t%f\t%s\n", figure,
    175            name.c_str(), flow_id, value, ylow, yhigh, error_title.c_str(), ymax,
    176            limit_title.c_str());
    177   }
    178 }
    179 
    180 void Logging::PlotLabel(int figure,
    181                         const std::string& title,
    182                         const std::string& y_label,
    183                         int num_flows) {
    184   CriticalSectionScoped cs(crit_sect_.get());
    185   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    186   assert(it != thread_map_.end());
    187   const State& state = it->second.stack.top();
    188   if (state.enabled) {
    189     printf("LABEL\t%d\t%s\t%s\t%d\n", figure, title.c_str(), y_label.c_str(),
    190            num_flows);
    191   }
    192 }
    193 
    194 Logging::Logging()
    195     : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
    196       thread_map_() {
    197 }
    198 
    199 Logging::State::State() : tag(""), timestamp_ms(0), enabled(true) {}
    200 
    201 Logging::State::State(const std::string& tag, int64_t timestamp_ms,
    202                       bool enabled)
    203     : tag(tag),
    204       timestamp_ms(timestamp_ms),
    205       enabled(enabled) {
    206 }
    207 
    208 void Logging::State::MergePrevious(const State& previous) {
    209   if (tag.empty()) {
    210     tag = previous.tag;
    211   } else if (!previous.tag.empty()) {
    212     tag = previous.tag + "_" + tag;
    213   }
    214   timestamp_ms = std::max(previous.timestamp_ms, timestamp_ms);
    215   enabled = previous.enabled && enabled;
    216 }
    217 
    218 void Logging::PushState(const std::string& append_to_tag, int64_t timestamp_ms,
    219                         bool enabled) {
    220   CriticalSectionScoped cs(crit_sect_.get());
    221   State new_state(append_to_tag, timestamp_ms, enabled);
    222   ThreadState* thread_state = &thread_map_[rtc::CurrentThreadId()];
    223   std::stack<State>* stack = &thread_state->stack;
    224   if (stack->empty()) {
    225     new_state.MergePrevious(thread_state->global_state);
    226   } else {
    227     new_state.MergePrevious(stack->top());
    228   }
    229   stack->push(new_state);
    230 }
    231 
    232 void Logging::PopState() {
    233   CriticalSectionScoped cs(crit_sect_.get());
    234   ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
    235   assert(it != thread_map_.end());
    236   std::stack<State>* stack = &it->second.stack;
    237   int64_t newest_timestamp_ms = stack->top().timestamp_ms;
    238   stack->pop();
    239   if (!stack->empty()) {
    240     State* state = &stack->top();
    241     // Update time so that next log/plot will use the latest time seen so far
    242     // in this call tree.
    243     state->timestamp_ms = std::max(state->timestamp_ms, newest_timestamp_ms);
    244   }
    245 }
    246 }  // namespace bwe
    247 }  // namespace testing
    248 }  // namespace webrtc
    249 
    250 #endif  // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
    251