blob: 8a58cc0dca800caccfb4e378f9555247a4538bdd [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//==============================================================================
//
#include "pw_trace_tokenized/trace_buffer_log.h"
#include "pw_base64/base64.h"
#include "pw_log/log.h"
#include "pw_span/span.h"
#include "pw_string/string_builder.h"
#include "pw_trace_tokenized/trace_buffer.h"
namespace pw {
namespace trace {
namespace {
constexpr int kMaxEntrySize = PW_TRACE_BUFFER_MAX_BLOCK_SIZE_BYTES;
constexpr int kMaxEntrySizeBase64 = pw::base64::EncodedSize(kMaxEntrySize);
constexpr int kLineLength = 80;
class ScopedTracePause {
public:
ScopedTracePause() : was_enabled_(pw_trace_IsEnabled()) {
PW_TRACE_SET_ENABLED(false);
}
~ScopedTracePause() { PW_TRACE_SET_ENABLED(was_enabled_); }
private:
bool was_enabled_;
};
} // namespace
pw::Status DumpTraceBufferToLog() {
std::byte line_buffer[kLineLength] = {};
std::byte entry_buffer[kMaxEntrySize + 1] = {};
char entry_base64_buffer[kMaxEntrySizeBase64] = {};
pw::StringBuilder line_builder(line_buffer);
ScopedTracePause pause_trace;
pw::ring_buffer::PrefixedEntryRingBuffer* trace_buffer =
pw::trace::GetBuffer();
size_t bytes_read = 0;
PW_LOG_INFO("[TRACE] begin");
while (trace_buffer->PeekFront(span(entry_buffer).subspan(1), &bytes_read) !=
pw::Status::OutOfRange()) {
trace_buffer->PopFront()
.IgnoreError(); // TODO(b/242598609): Handle Status properly
entry_buffer[0] = static_cast<std::byte>(bytes_read);
// The entry buffer is formatted as (size, entry) with an extra byte as
// a header to the entry. The calcuation of bytes_read + 1 represents
// the extra size header.
size_t to_write = pw::base64::Encode(span(entry_buffer, bytes_read + 1),
span(entry_base64_buffer));
size_t space_left = line_builder.max_size() - line_builder.size();
size_t written = 0;
while (to_write - written >= space_left) {
line_builder.append(entry_base64_buffer + written, space_left);
PW_LOG_INFO("[TRACE] data: %s", line_builder.c_str());
line_builder.clear();
written += space_left;
space_left = line_builder.max_size();
}
line_builder.append(entry_base64_buffer + written, to_write - written);
}
if (!line_builder.empty()) {
PW_LOG_INFO("[TRACE] data: %s", line_builder.c_str());
}
PW_LOG_INFO("[TRACE] end");
return pw::OkStatus();
}
} // namespace trace
} // namespace pw