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 23namespace webrtc { 24namespace testing { 25namespace bwe { 26 27Logging Logging::g_Logging; 28 29static 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 40Logging::Context::Context(uint32_t name, int64_t timestamp_ms, bool enabled) { 41 Logging::GetInstance()->PushState(ToString(name), timestamp_ms, enabled); 42} 43 44Logging::Context::Context(const std::string& name, int64_t timestamp_ms, 45 bool enabled) { 46 Logging::GetInstance()->PushState(name, timestamp_ms, enabled); 47} 48 49Logging::Context::Context(const char* name, int64_t timestamp_ms, 50 bool enabled) { 51 Logging::GetInstance()->PushState(name, timestamp_ms, enabled); 52} 53 54Logging::Context::~Context() { 55 Logging::GetInstance()->PopState(); 56} 57 58Logging* Logging::GetInstance() { 59 return &g_Logging; 60} 61 62void Logging::SetGlobalContext(uint32_t name) { 63 CriticalSectionScoped cs(crit_sect_.get()); 64 thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = ToString(name); 65} 66 67void Logging::SetGlobalContext(const std::string& name) { 68 CriticalSectionScoped cs(crit_sect_.get()); 69 thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = name; 70} 71 72void Logging::SetGlobalContext(const char* name) { 73 CriticalSectionScoped cs(crit_sect_.get()); 74 thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = name; 75} 76 77void Logging::SetGlobalEnable(bool enabled) { 78 CriticalSectionScoped cs(crit_sect_.get()); 79 thread_map_[ThreadWrapper::GetThreadId()].global_state.enabled = enabled; 80} 81 82void 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 97void 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 108Logging::Logging() 109 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), 110 thread_map_() { 111} 112 113Logging::State::State() : tag(""), timestamp_ms(0), enabled(true) {} 114 115Logging::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 122void 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 132void 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 146void 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