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