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_log_config.h" 37 #include "tls.h" 38 #include "template.h" 39 #include "util.h" 40 41 using namespace nghttp2; 42 43 #define ENABLE_LOG 1 44 45 #define LOG_ENABLED(SEVERITY) (ENABLE_LOG && shrpx::Log::log_enabled(SEVERITY)) 46 47 #ifdef __FILE_NAME__ 48 # define NGHTTP2_FILE_NAME __FILE_NAME__ 49 #else // !__FILE_NAME__ 50 # define NGHTTP2_FILE_NAME __FILE__ 51 #endif // !__FILE_NAME__ 52 53 #define LOG(SEVERITY) shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) 54 55 // Listener log 56 #define LLOG(SEVERITY, LISTEN) \ 57 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 58 << "[LISTEN:" << LISTEN << "] ") 59 60 // Worker log 61 #define WLOG(SEVERITY, WORKER) \ 62 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 63 << "[WORKER:" << WORKER << "] ") 64 65 // ClientHandler log 66 #define CLOG(SEVERITY, CLIENT_HANDLER) \ 67 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 68 << "[CLIENT_HANDLER:" << CLIENT_HANDLER << "] ") 69 70 // Upstream log 71 #define ULOG(SEVERITY, UPSTREAM) \ 72 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 73 << "[UPSTREAM:" << UPSTREAM << "] ") 74 75 // Downstream log 76 #define DLOG(SEVERITY, DOWNSTREAM) \ 77 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 78 << "[DOWNSTREAM:" << DOWNSTREAM << "] ") 79 80 // Downstream connection log 81 #define DCLOG(SEVERITY, DCONN) \ 82 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 83 << "[DCONN:" << DCONN << "] ") 84 85 // Downstream HTTP2 session log 86 #define SSLOG(SEVERITY, HTTP2) \ 87 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 88 << "[DHTTP2:" << HTTP2 << "] ") 89 90 // Memcached connection log 91 #define MCLOG(SEVERITY, MCONN) \ 92 (shrpx::Log(SEVERITY, NGHTTP2_FILE_NAME, __LINE__) \ 93 << "[MCONN:" << MCONN << "] ") 94 95 namespace shrpx { 96 97 class Downstream; 98 struct DownstreamAddr; 99 struct LoggingConfig; 100 101 enum SeverityLevel { INFO, NOTICE, WARN, ERROR, FATAL }; 102 103 using LogBuffer = std::array<uint8_t, 4_k>; 104 105 class Log { 106 public: 107 Log(int severity, const char *filename, int linenum); 108 ~Log(); 109 Log &operator<<(const std::string &s); 110 Log &operator<<(const char *s); 111 Log &operator<<(const StringRef &s); 112 Log &operator<<(const ImmutableString &s); 113 Log &operator<<(short n) { return *this << static_cast<long long>(n); } 114 Log &operator<<(int n) { return *this << static_cast<long long>(n); } 115 Log &operator<<(long n) { return *this << static_cast<long long>(n); } 116 Log &operator<<(long long n); 117 Log &operator<<(unsigned short n) { 118 return *this << static_cast<unsigned long long>(n); 119 } 120 Log &operator<<(unsigned int n) { 121 return *this << static_cast<unsigned long long>(n); 122 } 123 Log &operator<<(unsigned long n) { 124 return *this << static_cast<unsigned long long>(n); 125 } 126 Log &operator<<(unsigned long long n); 127 Log &operator<<(float n) { return *this << static_cast<double>(n); } 128 Log &operator<<(double n); 129 Log &operator<<(long double n); 130 Log &operator<<(bool n); 131 Log &operator<<(const void *p); 132 template <typename T> Log &operator<<(const std::shared_ptr<T> &ptr) { 133 return *this << ptr.get(); 134 } 135 Log &operator<<(void (*func)(Log &log)) { 136 func(*this); 137 return *this; 138 } write_seq(InputIt first,InputIt last)139 template <typename InputIt> void write_seq(InputIt first, InputIt last) { 140 if (full_) { 141 return; 142 } 143 144 auto d = std::distance(first, last); 145 auto n = std::min(wleft(), static_cast<size_t>(d)); 146 last_ = std::copy(first, first + n, last_); 147 update_full(); 148 } 149 write_hex(T n)150 template <typename T> void write_hex(T n) { 151 if (full_) { 152 return; 153 } 154 155 if (n == 0) { 156 if (wleft() < 4 /* for "0x00" */) { 157 full_ = true; 158 return; 159 } 160 *last_++ = '0'; 161 *last_++ = 'x'; 162 *last_++ = '0'; 163 *last_++ = '0'; 164 update_full(); 165 return; 166 } 167 168 size_t nlen = 0; 169 for (auto t = n; t; t >>= 8, ++nlen) 170 ; 171 172 nlen *= 2; 173 174 if (wleft() < 2 /* for "0x" */ + nlen) { 175 full_ = true; 176 return; 177 } 178 179 *last_++ = '0'; 180 *last_++ = 'x'; 181 182 last_ += nlen; 183 update_full(); 184 185 auto p = last_ - 1; 186 for (; n; n >>= 8) { 187 uint8_t b = n & 0xff; 188 *p-- = util::LOWER_XDIGITS[b & 0xf]; 189 *p-- = util::LOWER_XDIGITS[b >> 4]; 190 } 191 } 192 static void set_severity_level(int severity); 193 // Returns the severity level by |name|. Returns -1 if |name| is 194 // unknown. 195 static int get_severity_level_by_name(const StringRef &name); log_enabled(int severity)196 static bool log_enabled(int severity) { return severity >= severity_thres_; } 197 198 enum { 199 fmt_dec = 0x00, 200 fmt_hex = 0x01, 201 }; 202 set_flags(int flags)203 void set_flags(int flags) { flags_ = flags; } 204 205 private: rleft()206 size_t rleft() { return last_ - begin_; } wleft()207 size_t wleft() { return end_ - last_; } update_full()208 void update_full() { full_ = last_ == end_; } 209 210 LogBuffer &buf_; 211 uint8_t *begin_; 212 uint8_t *end_; 213 uint8_t *last_; 214 const char *filename_; 215 uint32_t flags_; 216 int severity_; 217 int linenum_; 218 bool full_; 219 static int severity_thres_; 220 }; 221 222 namespace log { 223 void hex(Log &log); 224 void dec(Log &log); 225 } // namespace log 226 227 #define TTY_HTTP_HD (log_config()->errorlog_tty ? "\033[1;34m" : "") 228 #define TTY_RST (log_config()->errorlog_tty ? "\033[0m" : "") 229 230 enum class LogFragmentType { 231 NONE, 232 LITERAL, 233 REMOTE_ADDR, 234 TIME_LOCAL, 235 TIME_ISO8601, 236 REQUEST, 237 STATUS, 238 BODY_BYTES_SENT, 239 HTTP, 240 AUTHORITY, 241 REMOTE_PORT, 242 SERVER_PORT, 243 REQUEST_TIME, 244 PID, 245 ALPN, 246 TLS_CIPHER, 247 SSL_CIPHER = TLS_CIPHER, 248 TLS_PROTOCOL, 249 SSL_PROTOCOL = TLS_PROTOCOL, 250 TLS_SESSION_ID, 251 SSL_SESSION_ID = TLS_SESSION_ID, 252 TLS_SESSION_REUSED, 253 SSL_SESSION_REUSED = TLS_SESSION_REUSED, 254 TLS_SNI, 255 TLS_CLIENT_FINGERPRINT_SHA1, 256 TLS_CLIENT_FINGERPRINT_SHA256, 257 TLS_CLIENT_ISSUER_NAME, 258 TLS_CLIENT_SERIAL, 259 TLS_CLIENT_SUBJECT_NAME, 260 BACKEND_HOST, 261 BACKEND_PORT, 262 METHOD, 263 PATH, 264 PATH_WITHOUT_QUERY, 265 PROTOCOL_VERSION, 266 }; 267 268 struct LogFragment { 269 LogFragment(LogFragmentType type, StringRef value = ""_sr) typeLogFragment270 : type(type), value(std::move(value)) {} 271 LogFragmentType type; 272 StringRef value; 273 }; 274 275 struct LogSpec { 276 Downstream *downstream; 277 StringRef remote_addr; 278 StringRef alpn; 279 StringRef sni; 280 SSL *ssl; 281 std::chrono::high_resolution_clock::time_point request_end_time; 282 StringRef remote_port; 283 uint16_t server_port; 284 pid_t pid; 285 }; 286 287 void upstream_accesslog(const std::vector<LogFragment> &lf, 288 const LogSpec &lgsp); 289 290 int reopen_log_files(const LoggingConfig &loggingconf); 291 292 // Logs message when process whose pid is |pid| and exist status is 293 // |rstatus| exited. The |msg| is prepended to the log message. 294 void log_chld(pid_t pid, int rstatus, const char *msg); 295 296 void redirect_stderr_to_errorlog(const LoggingConfig &loggingconf); 297 298 // Makes internal copy of stderr (and possibly stdout in the future), 299 // which is then used as pointer to /dev/stderr or /proc/self/fd/2 300 void store_original_fds(); 301 302 // Restores the original stderr that was stored with copy_original_fds 303 // Used just before execv 304 void restore_original_fds(); 305 306 // Closes |fd| which was returned by open_log_file (see below) 307 // and sets it to -1. In the case that |fd| points to stdout or 308 // stderr, or is -1, the descriptor is not closed (but still set to -1). 309 void close_log_file(int &fd); 310 311 // Opens |path| with O_APPEND enabled. If file does not exist, it is 312 // created first. This function returns file descriptor referring the 313 // opened file if it succeeds, or -1. 314 int open_log_file(const char *path); 315 316 } // namespace shrpx 317 318 #endif // SHRPX_LOG_H 319