blob: 3ec85203983aa11c1611cf88ecbb9d79d1c0d43f [file] [log] [blame]
// Copyright 2019 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 "log_listener_log_sink.h"
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/logger.h>
#include <lib/syslog/wire_format.h>
namespace netemul {
namespace internal {
/*
* LogListenerLogSinkImpl
*
* public
*/
LogListenerLogSinkImpl::LogListenerLogSinkImpl(
fidl::InterfaceRequest<fuchsia::logger::LogListenerSafe> request, std::string prefix,
zx::socket log_sink, async_dispatcher_t* dispatcher)
: LogListenerImpl(std::move(request), "@" + prefix, dispatcher) {
if (log_sink.is_valid()) {
log_sock_ = std::move(log_sink);
} else {
auto svc_dir = sys::ServiceDirectory::CreateFromNamespace();
fuchsia::logger::LogSinkPtr log;
svc_dir->Connect(log.NewRequest(dispatcher));
zx::socket out;
zx::socket::create(ZX_SOCKET_DATAGRAM, &out, &log_sock_);
log->Connect(std::move(out));
}
}
/*
* LogListenerLogSinkImpl
*
* protected
*/
void LogListenerLogSinkImpl::LogImpl(fuchsia::logger::LogMessage m) {
fx_log_packet_t packet;
packet.metadata.dropped_logs = dropped_logs_;
packet.metadata.pid = m.pid;
packet.metadata.tid = m.tid;
packet.metadata.severity = m.severity;
packet.metadata.time = m.time;
bool inline_prefix = true;
if (m.tags.size() < FX_LOG_MAX_TAGS) {
m.tags.push_back(prefix_);
inline_prefix = false;
}
// insert tags:
size_t pos = 0;
for (const auto& tag : m.tags) {
auto len = tag.length();
if (len > FX_LOG_MAX_TAG_LEN - 1) {
len = FX_LOG_MAX_TAG_LEN - 1;
}
packet.data[pos] = len;
pos++;
memcpy(&packet.data[pos], tag.c_str(), len);
pos += len;
}
packet.data[pos++] = 0;
if (inline_prefix && prefix_.length() + 4 + pos < sizeof(packet.data)) {
packet.data[pos++] = '[';
memcpy(&packet.data[pos], prefix_.c_str(), prefix_.length());
pos += prefix_.length();
packet.data[pos++] = ']';
packet.data[pos++] = ' ';
}
ZX_ASSERT(pos <= sizeof(packet.data));
auto remain = sizeof(packet.data) - pos;
if (m.msg.length() + 1 < remain) {
remain = m.msg.length() + 1;
}
if (remain > 0) {
memcpy(&packet.data[pos], m.msg.c_str(), remain);
packet.data[pos + remain - 1] = 0;
pos += remain;
}
size_t actual;
pos += sizeof(packet.metadata);
if (log_sock_.write(0, &packet, pos, &actual) == ZX_OK && actual == pos) {
dropped_logs_ = 0;
} else {
dropped_logs_++;
}
}
} // namespace internal
} // namespace netemul