blob: f0c862a0e5ad3e231b0571a12f7828d68a58a1ae [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
15#include "platform/api/trace_logging.h"
16#include "platform/impl/logging.h"
17
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
83bool IsLoggingOn(LogLevel level, absl::string_view file) {
84 // 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,
90 absl::string_view file,
91 int line,
92 absl::string_view msg) {
93 if (level < g_log_level)
94 return;
95
96 std::stringstream ss;
97 ss << "[" << level << ":" << file << "(" << line << "):T" << std::hex
98 << TRACE_CURRENT_ID << "] " << msg << '\n';
99 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