65static int syslog_facility = 0;
71typedef BOOL (WINAPI * PFInitializeCriticalSectionAndSpinCount) (LPCRITICAL_SECTION, DWORD);
91 void reset(FILE *newFile,
const char *newName);
224 const char *
const name =
nullptr;
263 bool enabled(
const int messageDebugLevel)
const;
365 sectionLevel = level;
370LabelThisProcess(
const char *
const name,
const std::optional<int>
id = std::optional<int>())
374 std::stringstream os;
376 if (
id.has_value()) {
388 if (
const auto parentProcessDebugOptions = getenv(
"SQUID_DEBUG")) {
403 debugs(84, 2,
"starting " << name <<
" with PID " << getpid());
556 auto &
module = Module();
557 (void)module.cacheLogChannel.releaseEarlyMessages();
558 (void)module.stderrChannel.releaseEarlyMessages();
559 (void)module.syslogChannel.releaseEarlyMessages();
573 assert(&channelA != channelBOrNil);
579 const auto writtenEarlier = channelA.
written;
581 std::merge(as.begin(), as.end(), bs.begin(), bs.end(),
Logger(channelA),
586 const auto writtenNow = channelA.
written - writtenEarlier;
587 if (
const auto totalCount = as.size() + bs.size()) {
588 debugs(0, 5,
"wrote " << writtenNow <<
" out of " << totalCount <<
'=' <<
589 as.size() <<
'+' << bs.size() <<
" early messages to " << channelA.
name);
615 fprintf(&destination,
"%s%s| %s\n",
716 stderrChannel.enabled(
DBG_DATA) ?
"; stderr will see all messages":
717 stderrChannel.enabled(
DBG_CRITICAL) ?
"; stderr will not see some messages":
718 "; stderr will see no messages";
735 recordNumber(aRecordNumber),
736 section(context.section),
737 level(context.level),
738 forceAlert(context.forceAlert)
758 assert(newFile != stderr || !stderr);
787 HMODULE krnl_lib = GetModuleHandle(
"Kernel32");
788 PFInitializeCriticalSectionAndSpinCount InitializeCriticalSectionAndSpinCount =
nullptr;
791 InitializeCriticalSectionAndSpinCount =
792 (PFInitializeCriticalSectionAndSpinCount) GetProcAddress(krnl_lib,
793 "InitializeCriticalSectionAndSpinCount");
795 dbg_mutex =
static_cast<CRITICAL_SECTION*
>(
xcalloc(1,
sizeof(CRITICAL_SECTION)));
797 if (InitializeCriticalSectionAndSpinCount) {
800 if (!InitializeCriticalSectionAndSpinCount(
dbg_mutex, 4000)) {
802 fprintf(logFile,
"FATAL: %s: can't initialize critical section\n", __func__);
806 fprintf(stderr,
"FATAL: %s: can't initialize critical section\n", __func__);
831 if (!strncasecmp(arg,
"rotate=", 7)) {
835 }
else if (!strncasecmp(arg,
"ALL", 3)) {
840 while (*arg && *arg++ !=
',');
869 const char *logfilename;
870 if (strncmp(logfile,
"stdio:",6) == 0)
871 logfilename = logfile + 6;
873 logfilename = logfile;
875 if (
auto log = fopen(logfilename,
"a+")) {
882 const auto xerrno = errno;
888 debugs(0,
DBG_CRITICAL,
"ERROR: Cannot open cache_log (" << logfilename <<
") for writing;" <<
896static struct syslog_facility_name {
901syslog_facility_names[] = {
910 "authpriv", LOG_AUTHPRIV
1000 "local7", LOG_LOCAL7
1011_db_set_syslog(
const char *facility)
1018 syslog_facility = LOG_DAEMON;
1021 syslog_facility = LOG_LOCAL4;
1026 struct syslog_facility_name *n;
1028 for (n = syslog_facility_names; n->name; ++n) {
1029 if (strcmp(n->name, facility) == 0) {
1030 syslog_facility = n->facility;
1035 fprintf(stderr,
"unknown syslog facility '%s'\n", facility);
1041 fprintf(stderr,
"syslog facility type not supported on your system\n");
1052 (header.
level == 0 ? LOG_WARNING : LOG_NOTICE);
1058 syslog(SyslogPriority(header),
"%s", body.c_str());
1067 assert(!
"unreachable code because opened, shouldWrite() are always false");
1086 _db_set_syslog(facility);
1090 fatalf(
"Logging to syslog not available on this platform");
1101 debugs(0, 9,
"command-line -X overrides: " << options);
1147#if HAVE_SYSLOG && defined(LOG_LOCAL4)
1150 openlog(
APP_SHORTNAME, LOG_PID | LOG_NDELAY | LOG_CONS, syslog_facility);
1168 if (S_ISREG(sb.st_mode) == 0)
1193 if (rename(from, to) == -1) {
1194 const auto saved_errno = errno;
1207 if (remove(to) == -1) {
1208 const auto saved_errno = errno;
1214 if (rename(from, to) == -1) {
1215 const auto saved_errno = errno;
1217 << to <<
"failed: " <<
xstrerr(saved_errno));
1229 static char buf[128];
1230 static time_t last_t = 0;
1236 char buf2[
sizeof(buf)-4];
1237 const auto tm = localtime(&last_t);
1238 strftime(buf2,
sizeof(buf2),
"%Y/%m/%d %H:%M:%S", tm);
1239 buf2[
sizeof(buf2)-1] =
'\0';
1240 const auto sz = snprintf(buf,
sizeof(buf),
"%s.%03d", buf2,
static_cast<int>(t.tv_usec / 1000));
1241 assert(0 < sz && sz <
static_cast<int>(
sizeof(buf)));
1244 }
else if (t.tv_sec != last_t) {
1246 const auto tm = localtime(&last_t);
1247 const int sz = strftime(buf,
sizeof(buf),
"%Y/%m/%d %H:%M:%S", tm);
1248 assert(0 < sz && sz <=
static_cast<int>(
sizeof(buf)));
1251 buf[
sizeof(buf)-1] =
'\0';
1260xassert(
const char *msg,
const char *file,
int line)
1269 debugs(0,
DBG_CRITICAL,
"FATAL: assertion failed: " << file <<
":" << line <<
": \"" << msg <<
"\"");
1280 sectionLevel(Levels[aSection]),
1283 waitingForIdle(false)
1294 sectionLevel =
Levels[aSection];
1307 const static std::ostringstream cleanStream;
1308 buf.flags(cleanStream.flags() | std::ios::fixed);
1309 buf.width(cleanStream.width());
1334 assert(current->waitingForIdle);
1348 future =
new Context(section, level);
1352 future =
new Context(section, level);
1356 topContext->
rewind(section, level);
1357 future = topContext;
1378 past->
upper =
nullptr;
std::ostream & CurrentCodeContextDetail(std::ostream &os)
void log(char *format,...)
DebugChannel managing messages destined for the configured cache_log file.
void write(const DebugMessageHeader &, const CompiledDebugMessageBody &) final
write the corresponding debugs() message into the channel
bool shouldWrite(const DebugMessageHeader &) const final
a fully processed debugs(), ready to be logged
CompiledDebugMessage(const Header &, const Body &)
CompiledDebugMessageBody Body
Header header
debugs() meta-information; reflected in log line prefix
Body body
the log line after the prefix (without the newline)
output iterator for writing CompiledDebugMessages to a given channel
std::reference_wrapper< DebugChannel > channel
output destination
Logger & operator=(const CompiledDebugMessage &message)
std::output_iterator_tag iterator_category
a receiver of debugs() messages (e.g., stderr or cache.log)
DebugChannel(DebugChannel &&)=delete
DebugRecordCount written
the number of messages sent to the underlying channel so far
void saveMessage(const DebugMessageHeader &, const CompiledDebugMessageBody &)
stores the given early message (if possible) or forgets it (otherwise)
static void StopSavingAndLog(DebugChannel &, DebugChannel *=nullptr)
stop saving and log() any "early" messages, in recordNumber order
void noteWritten(const DebugMessageHeader &)
reacts to a written a debugs() message
void writeToStream(FILE &, const DebugMessageHeader &, const CompiledDebugMessageBody &)
Formats a validated debugs() record and writes it to the given FILE.
virtual ~DebugChannel()=default
EarlyMessages releaseEarlyMessages()
void log(const DebugMessageHeader &, const CompiledDebugMessageBody &)
std::unique_ptr< CompiledDebugMessages > EarlyMessages
void stopEarlyMessageCollection()
end early message buffering, logging any saved messages
bool collectingEarlyMessages() const
whether we are still expecting (and buffering) early messages
DebugChannel(const char *aName)
const char *const name
unique channel label for debugging
virtual void write(const DebugMessageHeader &, const CompiledDebugMessageBody &)=0
write the corresponding debugs() message into the channel
EarlyMessages earlyMessages
DebugRecordCount lastWrittenRecordNumber
DebugMessageHeader::recordNumber of the last message we wrote.
virtual bool shouldWrite(const DebugMessageHeader &) const =0
a named FILE with very-early/late usage safety mechanisms
friend void ResyncDebugLog(FILE *newFile)
a hack for low-level file descriptor manipulations in ipcCreate()
FILE * file()
an opened cache_log stream or nil
DebugFile(DebugFile &&)=delete
void clear()
go back to the initial state
FILE * file_
opened "real" file or nil; never stderr
void reset(FILE *newFile, const char *newName)
switches to the new pair, absorbing FILE and duping the name
SyslogChannel syslogChannel
CacheLogChannel cacheLogChannel
StderrChannel stderrChannel
void log(const DebugMessageHeader &, const CompiledDebugMessageBody &)
meta-information for debugs() or a similar debugging call
Context * upper
previous or parent record in nested debugging calls
std::ostringstream buf
debugs() output sink
int level
minimum debugging level required by the debugs() call
bool forceAlert
the current debugs() will be a syslog ALERT
void rewind(const int aSection, const int aLevel)
Optimization: avoids new Context creation for every debugs().
Context(const int aSectionLevel, const int aLevel)
static void ResetStderrLevel(int maxLevel)
static bool StderrEnabled()
static void parseOptions(char const *)
static void PrepareToDie()
static void ForgetSaved()
silently erases saved early debugs() messages (if any)
static bool Enabled(const int section, const int level)
whether debugging the given section and the given level produces output
static Context * Current
deepest active context; nil outside debugs()
static std::ostream & Extra(std::ostream &)
static void NameThisKid(int kidIdentifier)
static void LogMessage(const Context &)
broadcasts debugs() message to the logging channels
static void SettleSyslog()
static int Levels[MAX_DEBUG_SECTIONS]
static void Finish()
logs output buffer created in Start() and closes debugging context
static void NameThisHelper(const char *name)
static char * debugOptions
static void UseCacheLog()
static void FormatStream(std::ostream &)
configures default formatting for the debugging stream
static std::ostringstream & Start(const int section, const int level)
opens debugging context and returns output buffer
static void BanCacheLogUse()
static void ConfigureSyslog(const char *facility)
enables logging to syslog (using the specified facility, when not nil)
static void StopCacheLogUse()
static int Level()
minimum level required by the current debugs() call
static void EnsureDefaultStderrLevel(int maxDefault)
static void SettleStderr()
static void LogWaitingForIdle()
Logs messages of Finish()ed debugs() calls that were queued earlier.
static void ForceAlert()
configures the active debugging context to write syslog ALERT
static bool Busy()
whether new debugs() messages must be queued
static size_t LoggingConcurrencyLevel
the current number of protected callers
DebugChannel managing messages destined for "standard error stream" (stderr)
bool shouldWrite(const DebugMessageHeader &) const final
bool enabled(const int messageDebugLevel) const
void takeOver(CacheLogChannel &)
start to take care of past/saved and future cacheLovirtual gChannel messages
void write(const DebugMessageHeader &, const CompiledDebugMessageBody &) final
write the corresponding debugs() message into the channel
void stopCoveringForCacheLog()
stop providing a cache_log replacement (if we were providing it)
bool coveringForCacheLog
whether we are the last resort for logging debugs() messages
bool shouldWrite(const DebugMessageHeader &) const final
bool opened
whether openlog() was called
void write(const DebugMessageHeader &, const CompiledDebugMessageBody &) final
write the corresponding debugs() message into the channel
void fd_open(const int fd, unsigned int, const char *description)
void fd_close(const int fd)
void commSetCloseOnExec(int fd)
#define MAX_DEBUG_SECTIONS
#define debugs(SECTION, LEVEL, CONTENT)
void fatalf(const char *fmt,...)
void ResyncDebugLog(FILE *newFile)
a hack for low-level file descriptor manipulations in ipcCreate()
static DebugModule & Module()
safe access to the debugging module
static std::optional< int > ExplicitStderrLevel
std::deque< CompiledDebugMessage > CompiledDebugMessages
debugs() messages captured in LogMessage() call order
uint64_t DebugRecordCount
a counter related to the number of debugs() calls
static DebugModule * Module_
Debugging module singleton.
static void LabelThisProcess(const char *const name, const std::optional< int > id=std::optional< int >())
optimization: formats ProcessLabel once for frequent debugs() reuse
static Debug::Context * WaitingForIdle
static const char * debugLogTime(const timeval &)
static void debugOpenLog(const char *logfile)
static int DefaultStderrLevel
void _db_rotate_log(void)
static std::string ProcessLabel
pre-formatted name of the current process for debugs() messages (or empty)
void xassert(const char *msg, const char *file, int line)
static bool DidResetSections
static void ResetSections(const int level=DBG_IMPORTANT)
used for the side effect: fills Debug::Levels with the given level
static constexpr int EarlyMessagesLevel
early debugs() with higher level are not buffered and, hence, may be lost
std::string CompiledDebugMessageBody
The processed "content" (i.e. the last parameter) part of a debugs() call.
static void debugArg(const char *arg)
time_t getCurrentTime() STUB_RETVAL(0) int tvSubUsec(struct timeval
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
SQUIDCEXTERN LPCRITICAL_SECTION dbg_mutex
void * xcalloc(size_t n, size_t sz)
const char * xstrerr(int error)