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 
     20 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     21 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
     22 
     23 namespace webrtc {
     24 namespace testing {
     25 namespace bwe {
     26 
     27 Logging Logging::g_Logging;
     28 
     29 static std::string ToString(uint32_t v) {
     30   const size_t kBufferSize = 16;
     31   char string_buffer[kBufferSize] = {0};
     32 #if defined(_MSC_VER) && defined(_WIN32)
     33   _snprintf(string_buffer, kBufferSize - 1, "%08x", v);
     34 #else
     35   snprintf(string_buffer, kBufferSize, "%08x", v);
     36 #endif
     37   return string_buffer;
     38 }
     39 
     40 Logging::Context::Context(uint32_t name, int64_t timestamp_ms, bool enabled) {
     41   Logging::GetInstance()->PushState(ToString(name), timestamp_ms, enabled);
     42 }
     43 
     44 Logging::Context::Context(const std::string& name, int64_t timestamp_ms,
     45                           bool enabled) {
     46   Logging::GetInstance()->PushState(name, timestamp_ms, enabled);
     47 }
     48 
     49 Logging::Context::Context(const char* name, int64_t timestamp_ms,
     50                           bool enabled) {
     51   Logging::GetInstance()->PushState(name, timestamp_ms, enabled);
     52 }
     53 
     54 Logging::Context::~Context() {
     55   Logging::GetInstance()->PopState();
     56 }
     57 
     58 Logging* Logging::GetInstance() {
     59   return &g_Logging;
     60 }
     61 
     62 void Logging::SetGlobalContext(uint32_t name) {
     63   CriticalSectionScoped cs(crit_sect_.get());
     64   thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = ToString(name);
     65 }
     66 
     67 void Logging::SetGlobalContext(const std::string& name) {
     68   CriticalSectionScoped cs(crit_sect_.get());
     69   thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = name;
     70 }
     71 
     72 void Logging::SetGlobalContext(const char* name) {
     73   CriticalSectionScoped cs(crit_sect_.get());
     74   thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = name;
     75 }
     76 
     77 void Logging::SetGlobalEnable(bool enabled) {
     78   CriticalSectionScoped cs(crit_sect_.get());
     79   thread_map_[ThreadWrapper::GetThreadId()].global_state.enabled = enabled;
     80 }
     81 
     82 void Logging::Log(const char format[], ...) {
     83   CriticalSectionScoped cs(crit_sect_.get());
     84   ThreadMap::iterator it = thread_map_.find(ThreadWrapper::GetThreadId());
     85   assert(it != thread_map_.end());
     86   const State& state = it->second.stack.top();
     87   if (state.enabled) {
     88     printf("%s\t", state.tag.c_str());
     89     va_list args;
     90     va_start(args, format);
     91     vprintf(format, args);
     92     va_end(args);
     93     printf("\n");
     94   }
     95 }
     96 
     97 void Logging::Plot(double value) {
     98   CriticalSectionScoped cs(crit_sect_.get());
     99   ThreadMap::iterator it = thread_map_.find(ThreadWrapper::GetThreadId());
    100   assert(it != thread_map_.end());
    101   const State& state = it->second.stack.top();
    102   if (state.enabled) {
    103     printf("PLOT\t%s\t%f\t%f\n", state.tag.c_str(), state.timestamp_ms * 0.001,
    104            value);
    105   }
    106 }
    107 
    108 Logging::Logging()
    109     : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
    110       thread_map_() {
    111 }
    112 
    113 Logging::State::State() : tag(""), timestamp_ms(0), enabled(true) {}
    114 
    115 Logging::State::State(const std::string& tag, int64_t timestamp_ms,
    116                       bool enabled)
    117     : tag(tag),
    118       timestamp_ms(timestamp_ms),
    119       enabled(enabled) {
    120 }
    121 
    122 void Logging::State::MergePrevious(const State& previous) {
    123   if (tag == "") {
    124     tag = previous.tag;
    125   } else if (previous.tag != "") {
    126     tag = previous.tag + "_" + tag;
    127   }
    128   timestamp_ms = std::max(previous.timestamp_ms, timestamp_ms);
    129   enabled = previous.enabled && enabled;
    130 }
    131 
    132 void Logging::PushState(const std::string& append_to_tag, int64_t timestamp_ms,
    133                         bool enabled) {
    134   CriticalSectionScoped cs(crit_sect_.get());
    135   State new_state(append_to_tag, timestamp_ms, enabled);
    136   ThreadState* thread_state = &thread_map_[ThreadWrapper::GetThreadId()];
    137   std::stack<State>* stack = &thread_state->stack;
    138   if (stack->empty()) {
    139     new_state.MergePrevious(thread_state->global_state);
    140   } else {
    141     new_state.MergePrevious(stack->top());
    142   }
    143   stack->push(new_state);
    144 }
    145 
    146 void Logging::PopState() {
    147   CriticalSectionScoped cs(crit_sect_.get());
    148   ThreadMap::iterator it = thread_map_.find(ThreadWrapper::GetThreadId());
    149   assert(it != thread_map_.end());
    150   std::stack<State>* stack = &it->second.stack;
    151   int64_t newest_timestamp_ms = stack->top().timestamp_ms;
    152   stack->pop();
    153   if (!stack->empty()) {
    154     State* state = &stack->top();
    155     // Update time so that next log/plot will use the latest time seen so far
    156     // in this call tree.
    157     state->timestamp_ms = std::max(state->timestamp_ms, newest_timestamp_ms);
    158   }
    159 }
    160 }  // namespace bwe
    161 }  // namespace testing
    162 }  // namespace webrtc
    163 
    164 #endif  // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
    165