1 /* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2012 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef SHRPX_LOG_H 26 #define SHRPX_LOG_H 27 28 #include "shrpx.h" 29 30 #include <sys/types.h> 31 32 #include <memory> 33 #include <vector> 34 #include <chrono> 35 36 #include "shrpx_config.h" 37 #include "shrpx_log_config.h" 38 #include "tls.h" 39 #include "template.h" 40 #include "util.h" 41 42 using namespace nghttp2; 43 44 #define ENABLE_LOG 1 45 46 #define LOG_ENABLED(SEVERITY) (ENABLE_LOG && shrpx::Log::log_enabled(SEVERITY)) 47 48 #define LOG(SEVERITY) shrpx::Log(SEVERITY, __FILE__, __LINE__) 49 50 // Listener log 51 #define LLOG(SEVERITY, LISTEN) \ 52 (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[LISTEN:" << LISTEN << "] ") 53 54 // Worker log 55 #define WLOG(SEVERITY, WORKER) \ 56 (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[WORKER:" << WORKER << "] ") 57 58 // ClientHandler log 59 #define CLOG(SEVERITY, CLIENT_HANDLER) \ 60 (shrpx::Log(SEVERITY, __FILE__, __LINE__) \ 61 << "[CLIENT_HANDLER:" << CLIENT_HANDLER << "] ") 62 63 // Upstream log 64 #define ULOG(SEVERITY, UPSTREAM) \ 65 (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[UPSTREAM:" << UPSTREAM \ 66 << "]" \ 67 " ") 68 69 // Downstream log 70 #define DLOG(SEVERITY, DOWNSTREAM) \ 71 (shrpx::Log(SEVERITY, __FILE__, __LINE__) \ 72 << "[DOWNSTREAM:" << DOWNSTREAM << "] ") 73 74 // Downstream connection log 75 #define DCLOG(SEVERITY, DCONN) \ 76 (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[DCONN:" << DCONN << "] ") 77 78 // Downstream HTTP2 session log 79 #define SSLOG(SEVERITY, HTTP2) \ 80 (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[DHTTP2:" << HTTP2 << "] ") 81 82 // Memcached connection log 83 #define MCLOG(SEVERITY, MCONN) \ 84 (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[MCONN:" << MCONN << "] ") 85 86 namespace shrpx { 87 88 class Downstream; 89 struct DownstreamAddr; 90 91 enum SeverityLevel { INFO, NOTICE, WARN, ERROR, FATAL }; 92 93 using LogBuffer = std::array<uint8_t, 4_k>; 94 95 class Log { 96 public: 97 Log(int severity, const char *filename, int linenum); 98 ~Log(); 99 Log &operator<<(const std::string &s); 100 Log &operator<<(const char *s); 101 Log &operator<<(const StringRef &s); 102 Log &operator<<(const ImmutableString &s); 103 Log &operator<<(short n) { return *this << static_cast<long long>(n); } 104 Log &operator<<(int n) { return *this << static_cast<long long>(n); } 105 Log &operator<<(long n) { return *this << static_cast<long long>(n); } 106 Log &operator<<(long long n); 107 Log &operator<<(unsigned short n) { 108 return *this << static_cast<unsigned long long>(n); 109 } 110 Log &operator<<(unsigned int n) { 111 return *this << static_cast<unsigned long long>(n); 112 } 113 Log &operator<<(unsigned long n) { 114 return *this << static_cast<unsigned long long>(n); 115 } 116 Log &operator<<(unsigned long long n); 117 Log &operator<<(float n) { return *this << static_cast<double>(n); } 118 Log &operator<<(double n); 119 Log &operator<<(long double n); 120 Log &operator<<(bool n); 121 Log &operator<<(const void *p); 122 template <typename T> Log &operator<<(const std::shared_ptr<T> &ptr) { 123 return *this << ptr.get(); 124 } 125 Log &operator<<(void (*func)(Log &log)) { 126 func(*this); 127 return *this; 128 } write_seq(InputIt first,InputIt last)129 template <typename InputIt> void write_seq(InputIt first, InputIt last) { 130 if (full_) { 131 return; 132 } 133 134 auto d = std::distance(first, last); 135 auto n = std::min(wleft(), static_cast<size_t>(d)); 136 last_ = std::copy(first, first + n, last_); 137 update_full(); 138 } 139 write_hex(T n)140 template <typename T> void write_hex(T n) { 141 if (full_) { 142 return; 143 } 144 145 if (n == 0) { 146 if (wleft() < 4 /* for "0x00" */) { 147 full_ = true; 148 return; 149 } 150 *last_++ = '0'; 151 *last_++ = 'x'; 152 *last_++ = '0'; 153 *last_++ = '0'; 154 update_full(); 155 return; 156 } 157 158 size_t nlen = 0; 159 for (auto t = n; t; t >>= 8, ++nlen) 160 ; 161 162 nlen *= 2; 163 164 if (wleft() < 2 /* for "0x" */ + nlen) { 165 full_ = true; 166 return; 167 } 168 169 *last_++ = '0'; 170 *last_++ = 'x'; 171 172 last_ += nlen; 173 update_full(); 174 175 auto p = last_ - 1; 176 for (; n; n >>= 8) { 177 uint8_t b = n & 0xff; 178 *p-- = util::LOWER_XDIGITS[b & 0xf]; 179 *p-- = util::LOWER_XDIGITS[b >> 4]; 180 } 181 } 182 static void set_severity_level(int severity); 183 // Returns the severity level by |name|. Returns -1 if |name| is 184 // unknown. 185 static int get_severity_level_by_name(const StringRef &name); log_enabled(int severity)186 static bool log_enabled(int severity) { return severity >= severity_thres_; } 187 188 enum { 189 fmt_dec = 0x00, 190 fmt_hex = 0x01, 191 }; 192 set_flags(int flags)193 void set_flags(int flags) { flags_ = flags; } 194 195 private: rleft()196 size_t rleft() { return last_ - begin_; } wleft()197 size_t wleft() { return end_ - last_; } update_full()198 void update_full() { full_ = last_ == end_; } 199 200 LogBuffer &buf_; 201 uint8_t *begin_; 202 uint8_t *end_; 203 uint8_t *last_; 204 const char *filename_; 205 uint32_t flags_; 206 int severity_; 207 int linenum_; 208 bool full_; 209 static int severity_thres_; 210 }; 211 212 namespace log { 213 void hex(Log &log); 214 void dec(Log &log); 215 } // namespace log 216 217 #define TTY_HTTP_HD (log_config()->errorlog_tty ? "\033[1;34m" : "") 218 #define TTY_RST (log_config()->errorlog_tty ? "\033[0m" : "") 219 220 enum class LogFragmentType { 221 NONE, 222 LITERAL, 223 REMOTE_ADDR, 224 TIME_LOCAL, 225 TIME_ISO8601, 226 REQUEST, 227 STATUS, 228 BODY_BYTES_SENT, 229 HTTP, 230 AUTHORITY, 231 REMOTE_PORT, 232 SERVER_PORT, 233 REQUEST_TIME, 234 PID, 235 ALPN, 236 TLS_CIPHER, 237 SSL_CIPHER = TLS_CIPHER, 238 TLS_PROTOCOL, 239 SSL_PROTOCOL = TLS_PROTOCOL, 240 TLS_SESSION_ID, 241 SSL_SESSION_ID = TLS_SESSION_ID, 242 TLS_SESSION_REUSED, 243 SSL_SESSION_REUSED = TLS_SESSION_REUSED, 244 TLS_SNI, 245 TLS_CLIENT_FINGERPRINT_SHA1, 246 TLS_CLIENT_FINGERPRINT_SHA256, 247 TLS_CLIENT_ISSUER_NAME, 248 TLS_CLIENT_SERIAL, 249 TLS_CLIENT_SUBJECT_NAME, 250 BACKEND_HOST, 251 BACKEND_PORT, 252 METHOD, 253 PATH, 254 PATH_WITHOUT_QUERY, 255 PROTOCOL_VERSION, 256 }; 257 258 struct LogFragment { 259 LogFragment(LogFragmentType type, StringRef value = StringRef::from_lit("")) typeLogFragment260 : type(type), value(std::move(value)) {} 261 LogFragmentType type; 262 StringRef value; 263 }; 264 265 struct LogSpec { 266 Downstream *downstream; 267 StringRef remote_addr; 268 StringRef alpn; 269 StringRef sni; 270 SSL *ssl; 271 std::chrono::high_resolution_clock::time_point request_end_time; 272 StringRef remote_port; 273 uint16_t server_port; 274 pid_t pid; 275 }; 276 277 void upstream_accesslog(const std::vector<LogFragment> &lf, 278 const LogSpec &lgsp); 279 280 int reopen_log_files(const LoggingConfig &loggingconf); 281 282 // Logs message when process whose pid is |pid| and exist status is 283 // |rstatus| exited. The |msg| is prepended to the log message. 284 void log_chld(pid_t pid, int rstatus, const char *msg); 285 286 void redirect_stderr_to_errorlog(const LoggingConfig &loggingconf); 287 288 // Makes internal copy of stderr (and possibly stdout in the future), 289 // which is then used as pointer to /dev/stderr or /proc/self/fd/2 290 void store_original_fds(); 291 292 // Restores the original stderr that was stored with copy_original_fds 293 // Used just before execv 294 void restore_original_fds(); 295 296 // Closes |fd| which was returned by open_log_file (see below) 297 // and sets it to -1. In the case that |fd| points to stdout or 298 // stderr, or is -1, the descriptor is not closed (but still set to -1). 299 void close_log_file(int &fd); 300 301 // Opens |path| with O_APPEND enabled. If file does not exist, it is 302 // created first. This function returns file descriptor referring the 303 // opened file if it succeeds, or -1. 304 int open_log_file(const char *path); 305 306 } // namespace shrpx 307 308 #endif // SHRPX_LOG_H 309