From: Thomas Otto Date: Sat, 8 Feb 2020 16:04:28 +0000 (+0100) Subject: Move logging into separate file (#532) X-Git-Tag: v4.0~645 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3426a72a27633d3d203192b3b9ff1c132db69dd3;p=thirdparty%2Fccache.git Move logging into separate file (#532) --- diff --git a/Makefile.in b/Makefile.in index 1edafa607..2d0e367ee 100644 --- a/Makefile.in +++ b/Makefile.in @@ -61,6 +61,7 @@ non_third_party_sources = \ src/legacy_globals.cpp \ src/legacy_util.cpp \ src/lockfile.cpp \ + src/logging.cpp \ src/manifest.cpp \ src/result.cpp \ src/stats.cpp diff --git a/src/Stat.cpp b/src/Stat.cpp index c8b750afe..7b398ba69 100644 --- a/src/Stat.cpp +++ b/src/Stat.cpp @@ -18,7 +18,7 @@ #include "Stat.hpp" -#include "legacy_util.hpp" +#include "logging.hpp" #include "third_party/fmt/core.h" diff --git a/src/ZstdCompressor.cpp b/src/ZstdCompressor.cpp index 424f9ba7f..a5d16854b 100644 --- a/src/ZstdCompressor.cpp +++ b/src/ZstdCompressor.cpp @@ -19,7 +19,7 @@ #include "ZstdCompressor.hpp" #include "Error.hpp" -#include "legacy_util.hpp" +#include "logging.hpp" const uint8_t k_default_zstd_compression_level = -1; diff --git a/src/ccache.cpp b/src/ccache.cpp index b54f74716..8d35dcf6a 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -35,6 +35,7 @@ #include "hashutil.hpp" #include "language.hpp" #include "legacy_globals.hpp" +#include "logging.hpp" #include "manifest.hpp" #include "result.hpp" #include "stats.hpp" diff --git a/src/cleanup.cpp b/src/cleanup.cpp index 318f2ee5c..65589b6de 100644 --- a/src/cleanup.cpp +++ b/src/cleanup.cpp @@ -21,6 +21,7 @@ #include "CacheFile.hpp" #include "Config.hpp" +#include "logging.hpp" #include "stats.hpp" #include diff --git a/src/execute.cpp b/src/execute.cpp index 7ab4c0d47..0413efc96 100644 --- a/src/execute.cpp +++ b/src/execute.cpp @@ -23,6 +23,7 @@ #include "Stat.hpp" #include "Util.hpp" #include "ccache.hpp" +#include "logging.hpp" using nonstd::string_view; diff --git a/src/exitfn.cpp b/src/exitfn.cpp index ea7d2e68d..5f5d13758 100644 --- a/src/exitfn.cpp +++ b/src/exitfn.cpp @@ -19,6 +19,7 @@ #include "exitfn.hpp" #include "legacy_util.hpp" +#include "logging.hpp" struct exit_function { diff --git a/src/hash.cpp b/src/hash.cpp index 4e3c76f51..da0a813b5 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -20,6 +20,7 @@ #include "hash.hpp" #include "legacy_util.hpp" +#include "logging.hpp" #include diff --git a/src/hashutil.cpp b/src/hashutil.cpp index 44eacdf15..53e7f1e45 100644 --- a/src/hashutil.cpp +++ b/src/hashutil.cpp @@ -22,6 +22,7 @@ #include "args.hpp" #include "ccache.hpp" #include "execute.hpp" +#include "logging.hpp" #include "macroskip.hpp" #include "stats.hpp" diff --git a/src/legacy_util.cpp b/src/legacy_util.cpp index 613d5bf84..8aee912c3 100644 --- a/src/legacy_util.cpp +++ b/src/legacy_util.cpp @@ -17,10 +17,11 @@ // this program; if not, write to the Free Software Foundation, Inc., 51 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -#include "Config.hpp" +#include "legacy_util.hpp" + #include "Error.hpp" #include "Util.hpp" -#include "execute.hpp" +#include "logging.hpp" #include "third_party/fmt/core.h" @@ -29,9 +30,6 @@ #ifdef HAVE_PWD_H # include #endif -#ifdef HAVE_SYSLOG_H -# include -#endif #ifdef HAVE_SYS_TIME_H # include #endif @@ -62,107 +60,6 @@ # include #endif -// Destination for g_config.log_file. -static FILE* logfile; - -// Whether to use syslog() instead. -static bool use_syslog; - -// Buffer used for logs in debug mode. -static char* debug_log_buffer; - -// Allocated debug_log_buffer size. -static size_t debug_log_buffer_capacity; - -// The amount of log data stored in debug_log_buffer. -static size_t debug_log_size; - -#define DEBUG_LOG_BUFFER_MARGIN 1024 - -static bool -init_log(void) -{ - if (debug_log_buffer || logfile || use_syslog) { - return true; - } - if (g_config.debug()) { - debug_log_buffer_capacity = DEBUG_LOG_BUFFER_MARGIN; - debug_log_buffer = static_cast(x_malloc(debug_log_buffer_capacity)); - debug_log_size = 0; - } - if (g_config.log_file().empty()) { - return g_config.debug(); - } -#ifdef HAVE_SYSLOG - if (g_config.log_file() == "syslog") { - use_syslog = true; - openlog("ccache", LOG_PID, LOG_USER); - return true; - } -#endif - logfile = fopen(g_config.log_file().c_str(), "a"); - if (logfile) { -#ifndef _WIN32 - set_cloexec_flag(fileno(logfile)); -#endif - return true; - } else { - return false; - } -} - -static void -append_to_debug_log(const char* s, size_t len) -{ - assert(debug_log_buffer); - if (debug_log_size + len + 1 > debug_log_buffer_capacity) { - debug_log_buffer_capacity += len + 1 + DEBUG_LOG_BUFFER_MARGIN; - debug_log_buffer = static_cast( - x_realloc(debug_log_buffer, debug_log_buffer_capacity)); - } - memcpy(debug_log_buffer + debug_log_size, s, len); - debug_log_size += len; -} - -static void -log_prefix(bool log_updated_time) -{ - static char prefix[200]; -#ifdef HAVE_GETTIMEOFDAY - if (log_updated_time) { - char timestamp[100]; - struct tm tm; - struct timeval tv; - gettimeofday(&tv, NULL); -# ifdef __MINGW64_VERSION_MAJOR - localtime_r((time_t*)&tv.tv_sec, &tm); -# else - localtime_r(&tv.tv_sec, &tm); -# endif - strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &tm); - snprintf(prefix, - sizeof(prefix), - "[%s.%06d %-5d] ", - timestamp, - (int)tv.tv_usec, - (int)getpid()); - } -#else - snprintf(prefix, sizeof(prefix), "[%-5d] ", (int)getpid()); -#endif - if (logfile) { - fputs(prefix, logfile); - } -#ifdef HAVE_SYSLOG - if (use_syslog) { - // prefix information will be added by syslog - } -#endif - if (debug_log_buffer) { - append_to_debug_log(prefix, strlen(prefix)); - } -} - static long path_max(const char* path) { @@ -178,122 +75,6 @@ path_max(const char* path) #endif } -static void warn_log_fail(void) ATTR_NORETURN; - -// Warn about failure writing to the log file and then exit. -static void -warn_log_fail(void) -{ - // Note: Can't call fatal() since that would lead to recursion. - fprintf(stderr, - "ccache: error: Failed to write to %s: %s\n", - g_config.log_file().c_str(), - strerror(errno)); - x_exit(EXIT_FAILURE); -} - -static void -vlog(const char* format, va_list ap, bool log_updated_time) -{ - if (!init_log()) { - return; - } - - va_list aq; - va_copy(aq, ap); - log_prefix(log_updated_time); - if (logfile) { - int rc1 = vfprintf(logfile, format, ap); - int rc2 = fprintf(logfile, "\n"); - if (rc1 < 0 || rc2 < 0) { - warn_log_fail(); - } - } -#ifdef HAVE_SYSLOG - if (use_syslog) { - vsyslog(LOG_DEBUG, format, ap); - } -#endif - if (debug_log_buffer) { - char buf[8192]; - int len = vsnprintf(buf, sizeof(buf), format, aq); - if (len >= 0) { - append_to_debug_log(buf, std::min((size_t)len, sizeof(buf) - 1)); - append_to_debug_log("\n", 1); - } - } - va_end(aq); -} - -// Write a message to the log file (adding a newline) and flush. -void -cc_log(const char* format, ...) -{ - va_list ap; - va_start(ap, format); - vlog(format, ap, true); - va_end(ap); - if (logfile) { - fflush(logfile); - } -} - -// Write a message to the log file (adding a newline) without flushing and with -// a reused timestamp. -void -cc_bulklog(const char* format, ...) -{ - va_list ap; - va_start(ap, format); - vlog(format, ap, false); - va_end(ap); -} - -// Log an executed command to the CCACHE_LOGFILE location. -void -cc_log_argv(const char* prefix, char** argv) -{ - if (!init_log()) { - return; - } - - log_prefix(true); - if (logfile) { - fputs(prefix, logfile); - print_command(logfile, argv); - int rc = fflush(logfile); - if (rc) { - warn_log_fail(); - } - } -#ifdef HAVE_SYSLOG - if (use_syslog) { - char* s = format_command(argv); - syslog(LOG_DEBUG, "%s", s); - free(s); - } -#endif - if (debug_log_buffer) { - append_to_debug_log(prefix, strlen(prefix)); - char* s = format_command(argv); - append_to_debug_log(s, strlen(s)); - free(s); - } -} - -// Copy the current log memory buffer to an output file. -void -cc_dump_debug_log_buffer(const char* path) -{ - FILE* file = fopen(path, "w"); - if (file) { - (void)fwrite(debug_log_buffer, 1, debug_log_size, file); - fclose(file); - } else { - cc_log("Failed to open %s: %s", path, strerror(errno)); - } -} - // Something went badly wrong! void fatal(const char* format, ...) diff --git a/src/legacy_util.hpp b/src/legacy_util.hpp index 9b622ce91..d18266ecb 100644 --- a/src/legacy_util.hpp +++ b/src/legacy_util.hpp @@ -22,13 +22,6 @@ #include -void cc_log(const char* format, ...) ATTR_FORMAT(printf, 1, 2); -void cc_bulklog(const char* format, ...) ATTR_FORMAT(printf, 1, 2); -void cc_log_argv(const char* prefix, char** argv); -void cc_dump_debug_log_buffer(const char* path); -void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN; -void warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2); - bool copy_fd(int fd_in, int fd_out); bool clone_file(const char* src, const char* dest, bool via_tmp_file); bool copy_file(const char* src, const char* dest, bool via_tmp_file); diff --git a/src/lockfile.cpp b/src/lockfile.cpp index ce3029cf7..390bb587f 100644 --- a/src/lockfile.cpp +++ b/src/lockfile.cpp @@ -19,6 +19,7 @@ #include "lockfile.hpp" #include "Util.hpp" +#include "logging.hpp" // This function acquires a lockfile for the given path. Returns true if the // lock was acquired, otherwise false. If the lock has been considered stale diff --git a/src/logging.cpp b/src/logging.cpp new file mode 100644 index 000000000..44f5a6d3c --- /dev/null +++ b/src/logging.cpp @@ -0,0 +1,259 @@ +// Copyright (C) 2002 Andrew Tridgell +// Copyright (C) 2009-2020 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include "logging.hpp" + +#include "Config.hpp" +#include "execute.hpp" + +#ifdef HAVE_SYSLOG_H +# include +#endif +#ifdef HAVE_SYS_TIME_H +# include +#endif + +#ifdef __linux__ +# ifdef HAVE_SYS_IOCTL_H +# include +# endif +#endif + +#ifdef _WIN32 +# include +# include +# include +#endif + +// Destination for g_config.log_file. +static FILE* logfile; + +// Whether to use syslog() instead. +static bool use_syslog; + +// Buffer used for logs in debug mode. +static char* debug_log_buffer; + +// Allocated debug_log_buffer size. +static size_t debug_log_buffer_capacity; + +// The amount of log data stored in debug_log_buffer. +static size_t debug_log_size; + +#define DEBUG_LOG_BUFFER_MARGIN 1024 + +static bool +init_log(void) +{ + if (debug_log_buffer || logfile || use_syslog) { + return true; + } + if (g_config.debug()) { + debug_log_buffer_capacity = DEBUG_LOG_BUFFER_MARGIN; + debug_log_buffer = static_cast(x_malloc(debug_log_buffer_capacity)); + debug_log_size = 0; + } + if (g_config.log_file().empty()) { + return g_config.debug(); + } +#ifdef HAVE_SYSLOG + if (g_config.log_file() == "syslog") { + use_syslog = true; + openlog("ccache", LOG_PID, LOG_USER); + return true; + } +#endif + logfile = fopen(g_config.log_file().c_str(), "a"); + if (logfile) { +#ifndef _WIN32 + set_cloexec_flag(fileno(logfile)); +#endif + return true; + } else { + return false; + } +} + +static void +append_to_debug_log(const char* s, size_t len) +{ + assert(debug_log_buffer); + if (debug_log_size + len + 1 > debug_log_buffer_capacity) { + debug_log_buffer_capacity += len + 1 + DEBUG_LOG_BUFFER_MARGIN; + debug_log_buffer = static_cast( + x_realloc(debug_log_buffer, debug_log_buffer_capacity)); + } + memcpy(debug_log_buffer + debug_log_size, s, len); + debug_log_size += len; +} + +static void +log_prefix(bool log_updated_time) +{ + static char prefix[200]; +#ifdef HAVE_GETTIMEOFDAY + if (log_updated_time) { + char timestamp[100]; + struct tm tm; + struct timeval tv; + gettimeofday(&tv, NULL); +# ifdef __MINGW64_VERSION_MAJOR + localtime_r((time_t*)&tv.tv_sec, &tm); +# else + localtime_r(&tv.tv_sec, &tm); +# endif + strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &tm); + snprintf(prefix, + sizeof(prefix), + "[%s.%06d %-5d] ", + timestamp, + (int)tv.tv_usec, + (int)getpid()); + } +#else + snprintf(prefix, sizeof(prefix), "[%-5d] ", (int)getpid()); +#endif + if (logfile) { + fputs(prefix, logfile); + } +#ifdef HAVE_SYSLOG + if (use_syslog) { + // prefix information will be added by syslog + } +#endif + if (debug_log_buffer) { + append_to_debug_log(prefix, strlen(prefix)); + } +} + +static void warn_log_fail(void) ATTR_NORETURN; + +// Warn about failure writing to the log file and then exit. +static void +warn_log_fail(void) +{ + // Note: Can't call fatal() since that would lead to recursion. + fprintf(stderr, + "ccache: error: Failed to write to %s: %s\n", + g_config.log_file().c_str(), + strerror(errno)); + x_exit(EXIT_FAILURE); +} + +static void +vlog(const char* format, va_list ap, bool log_updated_time) +{ + if (!init_log()) { + return; + } + + va_list aq; + va_copy(aq, ap); + log_prefix(log_updated_time); + if (logfile) { + int rc1 = vfprintf(logfile, format, ap); + int rc2 = fprintf(logfile, "\n"); + if (rc1 < 0 || rc2 < 0) { + warn_log_fail(); + } + } +#ifdef HAVE_SYSLOG + if (use_syslog) { + vsyslog(LOG_DEBUG, format, ap); + } +#endif + if (debug_log_buffer) { + char buf[8192]; + int len = vsnprintf(buf, sizeof(buf), format, aq); + if (len >= 0) { + append_to_debug_log(buf, std::min((size_t)len, sizeof(buf) - 1)); + append_to_debug_log("\n", 1); + } + } + va_end(aq); +} + +// Write a message to the log file (adding a newline) and flush. +void +cc_log(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + vlog(format, ap, true); + va_end(ap); + if (logfile) { + fflush(logfile); + } +} + +// Write a message to the log file (adding a newline) without flushing and with +// a reused timestamp. +void +cc_bulklog(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + vlog(format, ap, false); + va_end(ap); +} + +// Log an executed command to the CCACHE_LOGFILE location. +void +cc_log_argv(const char* prefix, char** argv) +{ + if (!init_log()) { + return; + } + + log_prefix(true); + if (logfile) { + fputs(prefix, logfile); + print_command(logfile, argv); + int rc = fflush(logfile); + if (rc) { + warn_log_fail(); + } + } +#ifdef HAVE_SYSLOG + if (use_syslog) { + char* s = format_command(argv); + syslog(LOG_DEBUG, "%s", s); + free(s); + } +#endif + if (debug_log_buffer) { + append_to_debug_log(prefix, strlen(prefix)); + char* s = format_command(argv); + append_to_debug_log(s, strlen(s)); + free(s); + } +} + +// Copy the current log memory buffer to an output file. +void +cc_dump_debug_log_buffer(const char* path) +{ + FILE* file = fopen(path, "w"); + if (file) { + (void)fwrite(debug_log_buffer, 1, debug_log_size, file); + fclose(file); + } else { + cc_log("Failed to open %s: %s", path, strerror(errno)); + } +} diff --git a/src/logging.hpp b/src/logging.hpp new file mode 100644 index 000000000..52e7cc60b --- /dev/null +++ b/src/logging.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2020 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#pragma once + +#include "system.hpp" + +#include + +void cc_log(const char* format, ...) ATTR_FORMAT(printf, 1, 2); +void cc_bulklog(const char* format, ...) ATTR_FORMAT(printf, 1, 2); +void cc_log_argv(const char* prefix, char** argv); +void cc_dump_debug_log_buffer(const char* path); +void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN; +void warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2); diff --git a/src/manifest.cpp b/src/manifest.cpp index 3eafd87f0..3a9695490 100644 --- a/src/manifest.cpp +++ b/src/manifest.cpp @@ -29,6 +29,7 @@ #include "hash.hpp" #include "hashutil.hpp" #include "legacy_globals.hpp" +#include "logging.hpp" // Manifest data format // ==================== diff --git a/src/result.hpp b/src/result.hpp index d169a056a..535573b90 100644 --- a/src/result.hpp +++ b/src/result.hpp @@ -20,6 +20,8 @@ #include "system.hpp" +#include "logging.hpp" + #include #include diff --git a/src/stats.cpp b/src/stats.cpp index 02ce7aeb3..eaa7c3a42 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -27,6 +27,7 @@ #include "counters.hpp" #include "hashutil.hpp" #include "lockfile.hpp" +#include "logging.hpp" #include #include