1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/scoped_fx_logger.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <lib/component/incoming/cpp/protocol.h>
8*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/directory.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include <string_view>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/fuchsia_component_connect.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/fuchsia_logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/process/process.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker namespace base {
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker ScopedFxLogger::ScopedFxLogger() = default;
23*6777b538SAndroid Build Coastguard Worker ScopedFxLogger::~ScopedFxLogger() = default;
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker ScopedFxLogger::ScopedFxLogger(ScopedFxLogger&& other) = default;
26*6777b538SAndroid Build Coastguard Worker ScopedFxLogger& ScopedFxLogger::operator=(ScopedFxLogger&& other) = default;
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker // static
CreateForProcess(std::vector<std::string_view> tags)29*6777b538SAndroid Build Coastguard Worker ScopedFxLogger ScopedFxLogger::CreateForProcess(
30*6777b538SAndroid Build Coastguard Worker std::vector<std::string_view> tags) {
31*6777b538SAndroid Build Coastguard Worker // CHECK()ing or LOG()ing inside this function is safe, since it is only
32*6777b538SAndroid Build Coastguard Worker // called to initialize logging, not during individual logging operations.
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker auto log_sink_client_end = component::Connect<fuchsia_logger::LogSink>();
35*6777b538SAndroid Build Coastguard Worker if (log_sink_client_end.is_error()) {
36*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << FidlConnectionErrorMessage(log_sink_client_end);
37*6777b538SAndroid Build Coastguard Worker return {};
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker // Rather than relying on automatic LogSink attribution via COMPONENT_NAME,
41*6777b538SAndroid Build Coastguard Worker // prepend a tag based on the calling process' name. COMPONENT_NAME may be
42*6777b538SAndroid Build Coastguard Worker // mis-attributed, in some Component configurations, to a parent or caller
43*6777b538SAndroid Build Coastguard Worker // component, from which the process' LogSink service is routed.
44*6777b538SAndroid Build Coastguard Worker std::string program_name = base::CommandLine::ForCurrentProcess()
45*6777b538SAndroid Build Coastguard Worker ->GetProgram()
46*6777b538SAndroid Build Coastguard Worker .BaseName()
47*6777b538SAndroid Build Coastguard Worker .AsUTF8Unsafe();
48*6777b538SAndroid Build Coastguard Worker tags.insert(tags.begin(), program_name);
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker return CreateFromLogSink(std::move(log_sink_client_end.value()),
51*6777b538SAndroid Build Coastguard Worker std::move(tags));
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker // static
CreateFromLogSink(fidl::ClientEnd<fuchsia_logger::LogSink> log_sink_client_end,std::vector<std::string_view> tags)55*6777b538SAndroid Build Coastguard Worker ScopedFxLogger ScopedFxLogger::CreateFromLogSink(
56*6777b538SAndroid Build Coastguard Worker fidl::ClientEnd<fuchsia_logger::LogSink> log_sink_client_end,
57*6777b538SAndroid Build Coastguard Worker std::vector<std::string_view> tags) {
58*6777b538SAndroid Build Coastguard Worker // CHECK()ing or LOG()ing inside this function is safe, since it is only
59*6777b538SAndroid Build Coastguard Worker // called to initialize logging, not during individual logging operations.
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker // Attempts to create a kernel socket object should never fail.
62*6777b538SAndroid Build Coastguard Worker zx::socket local, remote;
63*6777b538SAndroid Build Coastguard Worker zx_status_t socket_status =
64*6777b538SAndroid Build Coastguard Worker zx::socket::create(ZX_SOCKET_DATAGRAM, &local, &remote);
65*6777b538SAndroid Build Coastguard Worker ZX_CHECK(socket_status == ZX_OK, socket_status)
66*6777b538SAndroid Build Coastguard Worker << "zx_socket_create() failed";
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker // ConnectStructured() may fail if e.g. the LogSink has disconnected already.
69*6777b538SAndroid Build Coastguard Worker fidl::SyncClient log_sink(std::move(log_sink_client_end));
70*6777b538SAndroid Build Coastguard Worker auto connect_structured_result =
71*6777b538SAndroid Build Coastguard Worker log_sink->ConnectStructured(std::move(remote));
72*6777b538SAndroid Build Coastguard Worker if (connect_structured_result.is_error()) {
73*6777b538SAndroid Build Coastguard Worker ZX_LOG(ERROR, connect_structured_result.error_value().status())
74*6777b538SAndroid Build Coastguard Worker << "ConnectStructured() failed";
75*6777b538SAndroid Build Coastguard Worker return {};
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker return ScopedFxLogger(std::move(tags), std::move(local));
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker
LogMessage(std::string_view file,uint32_t line_number,std::string_view msg,FuchsiaLogSeverity severity)81*6777b538SAndroid Build Coastguard Worker void ScopedFxLogger::LogMessage(std::string_view file,
82*6777b538SAndroid Build Coastguard Worker uint32_t line_number,
83*6777b538SAndroid Build Coastguard Worker std::string_view msg,
84*6777b538SAndroid Build Coastguard Worker FuchsiaLogSeverity severity) {
85*6777b538SAndroid Build Coastguard Worker if (!socket_.is_valid())
86*6777b538SAndroid Build Coastguard Worker return;
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker // It is not safe to use e.g. CHECK() or LOG() macros here, since those
89*6777b538SAndroid Build Coastguard Worker // may result in reentrancy if this instance is used for routing process-
90*6777b538SAndroid Build Coastguard Worker // global logs to the system logger.
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker fuchsia_syslog::LogBuffer buffer;
93*6777b538SAndroid Build Coastguard Worker buffer.BeginRecord(severity, cpp17::string_view(file.data(), file.size()),
94*6777b538SAndroid Build Coastguard Worker line_number, cpp17::string_view(msg.data(), msg.size()),
95*6777b538SAndroid Build Coastguard Worker socket_.borrow(), 0, base::Process::Current().Pid(),
96*6777b538SAndroid Build Coastguard Worker base::PlatformThread::CurrentId());
97*6777b538SAndroid Build Coastguard Worker for (const auto& tag : tags_) {
98*6777b538SAndroid Build Coastguard Worker buffer.WriteKeyValue("tag", tag);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker if (!buffer.FlushRecord())
101*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "fuchsia_syslog.LogBuffer.FlushRecord() failed\n");
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker
ScopedFxLogger(std::vector<std::string_view> tags,zx::socket socket)104*6777b538SAndroid Build Coastguard Worker ScopedFxLogger::ScopedFxLogger(std::vector<std::string_view> tags,
105*6777b538SAndroid Build Coastguard Worker zx::socket socket)
106*6777b538SAndroid Build Coastguard Worker : tags_(tags.begin(), tags.end()), socket_(std::move(socket)) {}
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker } // namespace base
109