blob: 2041077a1f4329b17d927e8d87ff91d911953d6c [file] [log] [blame]
Yuri Wiitalab7979032019-11-08 15:17:20 -08001// Copyright 2019 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
5#include <errno.h>
6#include <fcntl.h>
7#include <sys/stat.h>
8#include <sys/types.h>
9#include <unistd.h>
10
11#include <cstdlib>
12#include <iostream>
13#include <sstream>
14
Yuri Wiitalab7979032019-11-08 15:17:20 -080015#include "platform/impl/logging.h"
Yuri Wiitala8e6db3b2019-11-20 11:20:54 -080016#include "util/trace_logging.h"
Yuri Wiitalab7979032019-11-08 15:17:20 -080017
18namespace openscreen {
Yuri Wiitalab7979032019-11-08 15:17:20 -080019namespace {
20
21int g_log_fd = STDERR_FILENO;
22LogLevel g_log_level = LogLevel::kWarning;
23
24std::ostream& operator<<(std::ostream& os, const LogLevel& level) {
25 const char* level_string = "";
26 switch (level) {
27 case LogLevel::kVerbose:
28 level_string = "VERBOSE";
29 break;
30 case LogLevel::kInfo:
31 level_string = "INFO";
32 break;
33 case LogLevel::kWarning:
34 level_string = "WARNING";
35 break;
36 case LogLevel::kError:
37 level_string = "ERROR";
38 break;
39 case LogLevel::kFatal:
40 level_string = "FATAL";
41 break;
42 }
43 os << level_string;
44 return os;
45}
46
47} // namespace
48
49void SetLogFifoOrDie(const char* filename) {
50 if (g_log_fd != STDERR_FILENO) {
51 close(g_log_fd);
52 g_log_fd = STDERR_FILENO;
53 }
54
mark a. foltzb0b58912020-07-09 11:48:23 -070055 // Note: The use of OSP_CHECK/OSP_LOG_* here will log to stderr.
Yuri Wiitalab7979032019-11-08 15:17:20 -080056 struct stat st = {};
57 int open_result = -1;
58 if (stat(filename, &st) == -1 && errno == ENOENT) {
59 if (mkfifo(filename, 0644) == 0) {
60 open_result = open(filename, O_WRONLY);
61 OSP_CHECK_NE(open_result, -1)
62 << "open(" << filename << ") failed: " << strerror(errno);
63 } else {
64 OSP_LOG_FATAL << "mkfifo(" << filename << ") failed: " << strerror(errno);
65 }
66 } else if (S_ISFIFO(st.st_mode)) {
67 open_result = open(filename, O_WRONLY);
68 OSP_CHECK_NE(open_result, -1)
69 << "open(" << filename << ") failed: " << strerror(errno);
70 } else {
71 OSP_LOG_FATAL << "not a FIFO special file: " << filename;
72 }
73
74 // Direct all logging to the opened FIFO file.
75 g_log_fd = open_result;
76}
77
78void SetLogLevel(LogLevel level) {
79 g_log_level = level;
80}
81
Yuri Wiitala75ea15d2019-12-03 16:01:48 -080082bool IsLoggingOn(LogLevel level, const char* file) {
Yuri Wiitalab7979032019-11-08 15:17:20 -080083 // Possible future enhancement: Use glob patterns passed on the command-line
84 // to use a different logging level for certain files, like in Chromium.
85 return level >= g_log_level;
86}
87
88void LogWithLevel(LogLevel level,
Yuri Wiitala75ea15d2019-12-03 16:01:48 -080089 const char* file,
Yuri Wiitalab7979032019-11-08 15:17:20 -080090 int line,
Yuri Wiitala75ea15d2019-12-03 16:01:48 -080091 std::stringstream message) {
Yuri Wiitalab7979032019-11-08 15:17:20 -080092 if (level < g_log_level)
93 return;
94
95 std::stringstream ss;
96 ss << "[" << level << ":" << file << "(" << line << "):T" << std::hex
Yuri Wiitala75ea15d2019-12-03 16:01:48 -080097 << TRACE_CURRENT_ID << "] " << message.rdbuf() << '\n';
Yuri Wiitalab7979032019-11-08 15:17:20 -080098 const auto ss_str = ss.str();
99 const auto bytes_written = write(g_log_fd, ss_str.c_str(), ss_str.size());
100 OSP_DCHECK(bytes_written);
101}
102
103void Break() {
104#if defined(_DEBUG)
105 __builtin_trap();
106#else
107 std::abort();
108#endif
109}
110
Yuri Wiitalab7979032019-11-08 15:17:20 -0800111} // namespace openscreen