| // Copyright 2025 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <lib/syslog/cpp/host/encoder.h> |
| #include <lib/syslog/cpp/host/log_buffer.h> |
| |
| #include <cinttypes> |
| #include <iostream> |
| |
| namespace fuchsia_logging { |
| namespace { |
| |
| // Common initialization for all KV pairs. |
| // Returns the header for writing the value. |
| internal::MsgHeader* StartKv(LogBuffer* buffer, std::string_view key) { |
| auto header = internal::MsgHeader::CreatePtr(buffer); |
| if (!header->first_kv || header->has_msg) { |
| header->WriteChar(' '); |
| } |
| header->WriteString(key); |
| header->WriteChar('='); |
| header->first_kv = false; |
| return header; |
| } |
| |
| void WriteKeyValueLegacy(LogBuffer* buffer, std::string_view key, std::string_view value) { |
| // "tag" has special meaning to our logging API |
| if (key == "tag") { |
| auto header = internal::MsgHeader::CreatePtr(buffer); |
| auto tag_size = value.size() + 1; |
| header->user_tag = reinterpret_cast<char*>(buffer->data()) + buffer->data_size() - tag_size; |
| memcpy(header->user_tag, value.data(), value.size()); |
| header->user_tag[value.size()] = '\0'; |
| return; |
| } |
| auto header = StartKv(buffer, key); |
| header->WriteChar('"'); |
| if (memchr(value.data(), '"', value.size()) != nullptr) { |
| // Escape quotes in strings. |
| for (char c : value) { |
| if (c == '"') { |
| header->WriteChar('\\'); |
| } |
| header->WriteChar(c); |
| } |
| } else { |
| header->WriteString(value); |
| } |
| header->WriteChar('"'); |
| } |
| |
| void WriteKeyValueLegacy(LogBuffer* buffer, std::string_view key, int64_t value) { |
| auto header = StartKv(buffer, key); |
| char a_buffer[128]; |
| snprintf(a_buffer, 128, "%" PRId64, value); |
| header->WriteString(a_buffer); |
| } |
| |
| void WriteKeyValueLegacy(LogBuffer* buffer, std::string_view key, uint64_t value) { |
| auto header = StartKv(buffer, key); |
| char a_buffer[128]; |
| snprintf(a_buffer, 128, "%" PRIu64, value); |
| header->WriteString(a_buffer); |
| } |
| |
| void WriteKeyValueLegacy(LogBuffer* buffer, std::string_view key, double value) { |
| auto header = StartKv(buffer, key); |
| char a_buffer[128]; |
| snprintf(a_buffer, 128, "%f", value); |
| header->WriteString(a_buffer); |
| } |
| |
| void WriteKeyValueLegacy(LogBuffer* buffer, std::string_view key, bool value) { |
| auto header = StartKv(buffer, key); |
| header->WriteString(value ? "true" : "false"); |
| } |
| |
| } // namespace |
| |
| void LogBuffer::WriteKeyValue(std::string_view key, std::string_view value) { |
| WriteKeyValueLegacy(this, key, value); |
| } |
| |
| void LogBuffer::WriteKeyValue(std::string_view key, int64_t value) { |
| WriteKeyValueLegacy(this, key, value); |
| } |
| |
| void LogBuffer::WriteKeyValue(std::string_view key, uint64_t value) { |
| WriteKeyValueLegacy(this, key, value); |
| } |
| |
| void LogBuffer::WriteKeyValue(std::string_view key, double value) { |
| WriteKeyValueLegacy(this, key, value); |
| } |
| |
| void LogBuffer::WriteKeyValue(std::string_view key, bool value) { |
| WriteKeyValueLegacy(this, key, value); |
| } |
| |
| bool LogBuffer::Flush() { |
| auto header = internal::MsgHeader::CreatePtr(this); |
| *(header->offset++) = 0; |
| if (header->user_tag) { |
| auto tag = header->user_tag; |
| std::cerr << "[" << tag << "] "; |
| } |
| std::cerr << reinterpret_cast<const char*>(this->data()) << std::endl; |
| return true; |
| } |
| |
| } // namespace fuchsia_logging |