scoped_fx_logger.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/fuchsia/scoped_fx_logger.h"
  5. #include <lib/fdio/directory.h>
  6. #include "base/command_line.h"
  7. #include "base/files/file_path.h"
  8. #include "base/fuchsia/fuchsia_logging.h"
  9. #include "base/process/process.h"
  10. #include "base/strings/string_piece.h"
  11. #include "base/threading/platform_thread.h"
  12. namespace base {
  13. ScopedFxLogger::ScopedFxLogger() = default;
  14. ScopedFxLogger::~ScopedFxLogger() = default;
  15. ScopedFxLogger::ScopedFxLogger(ScopedFxLogger&& other) = default;
  16. ScopedFxLogger& ScopedFxLogger::operator=(ScopedFxLogger&& other) = default;
  17. // static
  18. ScopedFxLogger ScopedFxLogger::CreateForProcess(
  19. std::vector<base::StringPiece> tags) {
  20. // CHECK()ing or LOG()ing inside this function is safe, since it is only
  21. // called to initialize logging, not during individual logging operations.
  22. fuchsia::logger::LogSinkHandle log_sink;
  23. zx_status_t status =
  24. fdio_service_connect("/svc/fuchsia.logger.LogSink",
  25. log_sink.NewRequest().TakeChannel().release());
  26. if (status != ZX_OK) {
  27. ZX_LOG(ERROR, status) << "connect(LogSink) failed";
  28. return {};
  29. }
  30. // Rather than relying on automatic LogSink attribution via COMPONENT_NAME,
  31. // prepend a tag based on the calling process' name. COMPONENT_NAME may be
  32. // mis-attributed, in some Component configurations, to a parent or caller
  33. // component, from which the process' LogSink service is routed.
  34. std::string program_name = base::CommandLine::ForCurrentProcess()
  35. ->GetProgram()
  36. .BaseName()
  37. .AsUTF8Unsafe();
  38. tags.insert(tags.begin(), program_name);
  39. return CreateFromLogSink(std::move(log_sink), std::move(tags));
  40. }
  41. // static
  42. ScopedFxLogger ScopedFxLogger::CreateFromLogSink(
  43. fuchsia::logger::LogSinkHandle log_sink_handle,
  44. std::vector<base::StringPiece> tags) {
  45. // CHECK()ing or LOG()ing inside this function is safe, since it is only
  46. // called to initialize logging, not during individual logging operations.
  47. // Attempts to create a kernel socket object should never fail.
  48. zx::socket local, remote;
  49. zx_status_t status = zx::socket::create(ZX_SOCKET_DATAGRAM, &local, &remote);
  50. ZX_CHECK(status == ZX_OK, status) << "zx_socket_create() failed";
  51. // ConnectStructured() may fail if e.g. the LogSink has disconnected already.
  52. fuchsia::logger::LogSinkSyncPtr log_sink;
  53. log_sink.Bind(std::move(log_sink_handle));
  54. status = log_sink->ConnectStructured(std::move(remote));
  55. if (status != ZX_OK) {
  56. ZX_LOG(ERROR, status) << "ConnectStructured() failed";
  57. return {};
  58. }
  59. return ScopedFxLogger(std::move(tags), std::move(local));
  60. }
  61. void ScopedFxLogger::LogMessage(base::StringPiece file,
  62. uint32_t line_number,
  63. base::StringPiece msg,
  64. FuchsiaLogSeverity severity) {
  65. if (!socket_.is_valid())
  66. return;
  67. // It is not safe to use e.g. CHECK() or LOG() macros here, since those
  68. // may result in reentrancy if this instance is used for routing process-
  69. // global logs to the system logger.
  70. fuchsia_syslog::LogBuffer buffer;
  71. buffer.BeginRecord(severity, cpp17::string_view(file.data(), file.size()),
  72. line_number, cpp17::string_view(msg.data(), msg.size()),
  73. false, socket_.borrow(), 0, base::Process::Current().Pid(),
  74. base::PlatformThread::CurrentId());
  75. for (const auto& tag : tags_) {
  76. buffer.WriteKeyValue("tag", tag);
  77. }
  78. buffer.FlushRecord();
  79. }
  80. ScopedFxLogger::ScopedFxLogger(std::vector<base::StringPiece> tags,
  81. zx::socket socket)
  82. : tags_(tags.begin(), tags.end()), socket_(std::move(socket)) {}
  83. } // namespace base