1 /**
2  * Copyright (c) 2014, Timothy Stack
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  * * Neither the name of Timothy Stack nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * @file lnav_log.hh
30  */
31 
32 #ifndef lnav_log_hh
33 #define lnav_log_hh
34 
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <string>
39 
40 #ifndef lnav_dead2
41 #define lnav_dead2 __attribute__((noreturn))
42 #endif
43 
44 #include "optional.hpp"
45 
46 struct termios;
47 
48 enum class lnav_log_level_t : uint32_t {
49     TRACE,
50     DEBUG,
51     INFO,
52     WARNING,
53     ERROR,
54 };
55 
56 void log_argv(int argc, char *argv[]);
57 void log_host_info();
58 void log_rusage_raw(enum lnav_log_level_t level, const char *src_file, int line_number, const struct rusage &ru);
59 void log_msg(enum lnav_log_level_t level, const char *src_file, int line_number,
60     const char *fmt, ...);
61 void log_msg_extra(const char *fmt, ...);
62 void log_msg_extra_complete();
63 void log_install_handlers();
64 void log_abort() lnav_dead2;
65 void log_pipe_err(int fd);
66 void log_set_thread_prefix(std::string prefix);
67 
68 struct log_state_dumper {
69 public:
70     log_state_dumper();
71 
72     virtual ~log_state_dumper();
73 
log_statelog_state_dumper74     virtual void log_state() {
75 
76     };
77 
78     log_state_dumper(const log_state_dumper&) = delete;
79     log_state_dumper& operator=(const log_state_dumper&) = delete;
80 };
81 
82 struct log_crash_recoverer {
83 public:
84     log_crash_recoverer();
85 
86     virtual ~log_crash_recoverer();
87 
88     virtual void log_crash_recover() = 0;
89 };
90 
91 extern nonstd::optional<FILE *> lnav_log_file;
92 extern const char *lnav_log_crash_dir;
93 extern nonstd::optional<const struct termios *> lnav_log_orig_termios;
94 extern enum lnav_log_level_t lnav_log_level;
95 
96 #define log_msg_wrapper(level, fmt...) \
97     do { \
98         if (lnav_log_level <= level) { \
99             log_msg(level, __FILE__, __LINE__, fmt); \
100         } \
101     } \
102     while (false)
103 
104 #define log_rusage(level, ru) \
105     log_rusage_raw(level, __FILE__, __LINE__, ru);
106 
107 #define log_error(fmt...) \
108     log_msg_wrapper(lnav_log_level_t::ERROR, fmt);
109 
110 #define log_warning(fmt...) \
111     log_msg_wrapper(lnav_log_level_t::WARNING, fmt);
112 
113 #define log_info(fmt...) \
114     log_msg_wrapper(lnav_log_level_t::INFO, fmt);
115 
116 #define log_debug(fmt...) \
117     log_msg_wrapper(lnav_log_level_t::DEBUG, fmt);
118 
119 #define log_trace(fmt...) \
120     log_msg_wrapper(lnav_log_level_t::TRACE, fmt);
121 
122 #define require(e)  \
123     ((void) ((e) ? 0 : lnav_require (#e, __FILE__, __LINE__)))
124 #define lnav_require(e, file, line) \
125     (log_msg(lnav_log_level_t::ERROR, file, line, "failed precondition `%s'", e), log_abort(), 1)
126 
127 #define ensure(e)  \
128     ((void) ((e) ? 0 : lnav_ensure (#e, __FILE__, __LINE__)))
129 #define lnav_ensure(e, file, line) \
130     (log_msg(lnav_log_level_t::ERROR, file, line, "failed postcondition `%s'", e), log_abort(), 1)
131 
132 #define log_perror(e)  \
133     ((void) ((e != -1) ? 0 : lnav_log_perror (#e, __FILE__, __LINE__)))
134 #define lnav_log_perror(e, file, line) \
135     (log_msg(lnav_log_level_t::ERROR, file, line, "syscall failed `%s' -- %s", e, strerror(errno)), 1)
136 
137 #endif
138