xref: /aosp_15_r20/external/openscreen/platform/impl/logging_posix.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include <errno.h>
6*3f982cf4SFabien Sanglard #include <fcntl.h>
7*3f982cf4SFabien Sanglard #include <sys/stat.h>
8*3f982cf4SFabien Sanglard #include <sys/types.h>
9*3f982cf4SFabien Sanglard #include <unistd.h>
10*3f982cf4SFabien Sanglard 
11*3f982cf4SFabien Sanglard #include <cstdlib>
12*3f982cf4SFabien Sanglard #include <iostream>
13*3f982cf4SFabien Sanglard #include <sstream>
14*3f982cf4SFabien Sanglard 
15*3f982cf4SFabien Sanglard #include "platform/impl/logging.h"
16*3f982cf4SFabien Sanglard #include "platform/impl/logging_test.h"
17*3f982cf4SFabien Sanglard #include "util/trace_logging.h"
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard namespace openscreen {
20*3f982cf4SFabien Sanglard namespace {
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard int g_log_fd = STDERR_FILENO;
23*3f982cf4SFabien Sanglard LogLevel g_log_level = LogLevel::kWarning;
24*3f982cf4SFabien Sanglard std::vector<std::string>* g_log_messages_for_test = nullptr;
25*3f982cf4SFabien Sanglard 
operator <<(std::ostream & os,const LogLevel & level)26*3f982cf4SFabien Sanglard std::ostream& operator<<(std::ostream& os, const LogLevel& level) {
27*3f982cf4SFabien Sanglard   const char* level_string = "";
28*3f982cf4SFabien Sanglard   switch (level) {
29*3f982cf4SFabien Sanglard     case LogLevel::kVerbose:
30*3f982cf4SFabien Sanglard       level_string = "VERBOSE";
31*3f982cf4SFabien Sanglard       break;
32*3f982cf4SFabien Sanglard     case LogLevel::kInfo:
33*3f982cf4SFabien Sanglard       level_string = "INFO";
34*3f982cf4SFabien Sanglard       break;
35*3f982cf4SFabien Sanglard     case LogLevel::kWarning:
36*3f982cf4SFabien Sanglard       level_string = "WARNING";
37*3f982cf4SFabien Sanglard       break;
38*3f982cf4SFabien Sanglard     case LogLevel::kError:
39*3f982cf4SFabien Sanglard       level_string = "ERROR";
40*3f982cf4SFabien Sanglard       break;
41*3f982cf4SFabien Sanglard     case LogLevel::kFatal:
42*3f982cf4SFabien Sanglard       level_string = "FATAL";
43*3f982cf4SFabien Sanglard       break;
44*3f982cf4SFabien Sanglard   }
45*3f982cf4SFabien Sanglard   os << level_string;
46*3f982cf4SFabien Sanglard   return os;
47*3f982cf4SFabien Sanglard }
48*3f982cf4SFabien Sanglard 
49*3f982cf4SFabien Sanglard }  // namespace
50*3f982cf4SFabien Sanglard 
SetLogFifoOrDie(const char * filename)51*3f982cf4SFabien Sanglard void SetLogFifoOrDie(const char* filename) {
52*3f982cf4SFabien Sanglard   if (g_log_fd != STDERR_FILENO) {
53*3f982cf4SFabien Sanglard     close(g_log_fd);
54*3f982cf4SFabien Sanglard     g_log_fd = STDERR_FILENO;
55*3f982cf4SFabien Sanglard   }
56*3f982cf4SFabien Sanglard 
57*3f982cf4SFabien Sanglard   // Note: The use of OSP_CHECK/OSP_LOG_* here will log to stderr.
58*3f982cf4SFabien Sanglard   struct stat st = {};
59*3f982cf4SFabien Sanglard   int open_result = -1;
60*3f982cf4SFabien Sanglard   if (stat(filename, &st) == -1 && errno == ENOENT) {
61*3f982cf4SFabien Sanglard     if (mkfifo(filename, 0644) == 0) {
62*3f982cf4SFabien Sanglard       open_result = open(filename, O_WRONLY);
63*3f982cf4SFabien Sanglard       OSP_CHECK_NE(open_result, -1)
64*3f982cf4SFabien Sanglard           << "open(" << filename << ") failed: " << strerror(errno);
65*3f982cf4SFabien Sanglard     } else {
66*3f982cf4SFabien Sanglard       OSP_LOG_FATAL << "mkfifo(" << filename << ") failed: " << strerror(errno);
67*3f982cf4SFabien Sanglard     }
68*3f982cf4SFabien Sanglard   } else if (S_ISFIFO(st.st_mode)) {
69*3f982cf4SFabien Sanglard     open_result = open(filename, O_WRONLY);
70*3f982cf4SFabien Sanglard     OSP_CHECK_NE(open_result, -1)
71*3f982cf4SFabien Sanglard         << "open(" << filename << ") failed: " << strerror(errno);
72*3f982cf4SFabien Sanglard   } else {
73*3f982cf4SFabien Sanglard     OSP_LOG_FATAL << "not a FIFO special file: " << filename;
74*3f982cf4SFabien Sanglard   }
75*3f982cf4SFabien Sanglard 
76*3f982cf4SFabien Sanglard   // Direct all logging to the opened FIFO file.
77*3f982cf4SFabien Sanglard   g_log_fd = open_result;
78*3f982cf4SFabien Sanglard }
79*3f982cf4SFabien Sanglard 
SetLogLevel(LogLevel level)80*3f982cf4SFabien Sanglard void SetLogLevel(LogLevel level) {
81*3f982cf4SFabien Sanglard   g_log_level = level;
82*3f982cf4SFabien Sanglard }
83*3f982cf4SFabien Sanglard 
GetLogLevel()84*3f982cf4SFabien Sanglard LogLevel GetLogLevel() {
85*3f982cf4SFabien Sanglard   return g_log_level;
86*3f982cf4SFabien Sanglard }
87*3f982cf4SFabien Sanglard 
IsLoggingOn(LogLevel level,const char * file)88*3f982cf4SFabien Sanglard bool IsLoggingOn(LogLevel level, const char* file) {
89*3f982cf4SFabien Sanglard   // Possible future enhancement: Use glob patterns passed on the command-line
90*3f982cf4SFabien Sanglard   // to use a different logging level for certain files, like in Chromium.
91*3f982cf4SFabien Sanglard   return level >= g_log_level;
92*3f982cf4SFabien Sanglard }
93*3f982cf4SFabien Sanglard 
LogWithLevel(LogLevel level,const char * file,int line,std::stringstream message)94*3f982cf4SFabien Sanglard void LogWithLevel(LogLevel level,
95*3f982cf4SFabien Sanglard                   const char* file,
96*3f982cf4SFabien Sanglard                   int line,
97*3f982cf4SFabien Sanglard                   std::stringstream message) {
98*3f982cf4SFabien Sanglard   if (level < g_log_level)
99*3f982cf4SFabien Sanglard     return;
100*3f982cf4SFabien Sanglard 
101*3f982cf4SFabien Sanglard   std::stringstream ss;
102*3f982cf4SFabien Sanglard   ss << "[" << level << ":" << file << "(" << line << "):T" << std::hex
103*3f982cf4SFabien Sanglard      << TRACE_CURRENT_ID << "] " << message.rdbuf() << '\n';
104*3f982cf4SFabien Sanglard   const auto ss_str = ss.str();
105*3f982cf4SFabien Sanglard   const auto bytes_written = write(g_log_fd, ss_str.c_str(), ss_str.size());
106*3f982cf4SFabien Sanglard   OSP_DCHECK(bytes_written);
107*3f982cf4SFabien Sanglard   if (g_log_messages_for_test) {
108*3f982cf4SFabien Sanglard     g_log_messages_for_test->push_back(ss_str);
109*3f982cf4SFabien Sanglard   }
110*3f982cf4SFabien Sanglard }
111*3f982cf4SFabien Sanglard 
Break()112*3f982cf4SFabien Sanglard [[noreturn]] void Break() {
113*3f982cf4SFabien Sanglard // Generally this will just resolve to an abort anyways, but gives the
114*3f982cf4SFabien Sanglard // compiler a chance to peform a more appropriate, target specific trap
115*3f982cf4SFabien Sanglard // as appropriate.
116*3f982cf4SFabien Sanglard #if defined(_DEBUG)
117*3f982cf4SFabien Sanglard   __builtin_trap();
118*3f982cf4SFabien Sanglard #else
119*3f982cf4SFabien Sanglard   std::abort();
120*3f982cf4SFabien Sanglard #endif
121*3f982cf4SFabien Sanglard }
122*3f982cf4SFabien Sanglard 
SetLogBufferForTest(std::vector<std::string> * messages)123*3f982cf4SFabien Sanglard void SetLogBufferForTest(std::vector<std::string>* messages) {
124*3f982cf4SFabien Sanglard   g_log_messages_for_test = messages;
125*3f982cf4SFabien Sanglard }
126*3f982cf4SFabien Sanglard 
127*3f982cf4SFabien Sanglard }  // namespace openscreen
128