GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 225 326 69.0%
Branches: 157 303 51.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * LogCvmfs() handles all message output. It works like printf.
5 * It can log to a debug log file, stdout, stderr, and syslog.
6 * The tracer is a separate module, messages do not overlap with logging.
7 *
8 * The syslog setter routines are not thread-safe. They are meant to be
9 * invoked at the very first, single-threaded stage.
10 *
11 * If DEBUGMSG is undefined, pure debug messages are compiled into no-ops.
12 */
13
14 #include "util/logging_internal.h" // NOLINT(build/include)
15
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <pthread.h>
19 #include <syslog.h>
20 #include <time.h>
21 #include <unistd.h>
22
23 #include <cassert>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <ctime>
28 #include <vector>
29
30 #include "util/export.h"
31 #include "util/mutex.h"
32 #include "util/platform.h"
33 #include "util/posix.h"
34 #include "util/single_copy.h"
35 #include "util/smalloc.h"
36
37 using namespace std; // NOLINT
38
39 #ifdef CVMFS_NAMESPACE_GUARD
40 namespace CVMFS_NAMESPACE_GUARD {
41 #endif
42
43 static void LogCustom(unsigned id, const std::string &message);
44
45 LogFacilities DefaultLogging::info = kLogSyslog;
46 LogFacilities DefaultLogging::error = kLogSyslogErr;
47
48 void DefaultLogging::Set(LogFacilities info, LogFacilities error) {
49 DefaultLogging::info = info;
50 DefaultLogging::error = error;
51 }
52
53 namespace {
54
55 unsigned gMicroSyslogMax = 500 * 1024; // default: rotate after 500kB
56
57 pthread_mutex_t lock_stdout = PTHREAD_MUTEX_INITIALIZER;
58 pthread_mutex_t lock_stderr = PTHREAD_MUTEX_INITIALIZER;
59 #ifdef DEBUGMSG
60 pthread_mutex_t lock_debug = PTHREAD_MUTEX_INITIALIZER;
61 FILE *file_debug = NULL;
62 string *path_debug = NULL;
63 #endif
64 const char *module_names[] = {
65 "unknown", "cache", "catalog", "sql",
66 "cvmfs", "hash", "download", "compress",
67 "quota", "talk", "monitor", "lru",
68 "fuse stub", "signature", "fs traversal", "catalog traversal",
69 "nfs maps", "publish", "spooler", "concurrency",
70 "utility", "glue buffer", "history", "unionfs",
71 "pathspec", "receiver", "upload s3", "upload http",
72 "s3fanout", "gc", "dns", "authz",
73 "reflog", "kvstore", "telemetry", "curl"};
74 int syslog_facility = LOG_USER;
75 int syslog_level = LOG_NOTICE;
76 char *syslog_prefix = NULL;
77
78 string *usyslog_dest = NULL;
79 int usyslog_fd = -1;
80 int usyslog_fd1 = -1;
81 unsigned usyslog_size = 0;
82 pthread_mutex_t lock_usyslock = PTHREAD_MUTEX_INITIALIZER;
83
84 const unsigned kMaxCustomlog = 3;
85 string *customlog_dests[] = {NULL, NULL, NULL};
86 int customlog_fds[] = {-1, -1, -1};
87 pthread_mutex_t customlog_locks[] = {
88 PTHREAD_MUTEX_INITIALIZER,
89 PTHREAD_MUTEX_INITIALIZER,
90 PTHREAD_MUTEX_INITIALIZER};
91
92 LogLevels max_log_level = kLogNormal;
93 static void (*alt_log_func)(const LogSource source, const int mask,
94 const char *msg) = NULL;
95
96 /**
97 * Circular buffer of the last $n$ calls to LogCvmfs(). Thread-safe class.
98 */
99 class LogBuffer : SingleCopy {
100 public:
101 3 LogBuffer() : next_id_(0) {
102 3 int retval = pthread_mutex_init(&lock_, NULL);
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(retval == 0);
104 3 }
105
106 56 ~LogBuffer() {
107 56 pthread_mutex_destroy(&lock_);
108 56 }
109
110 499173 void Append(const LogBufferEntry &entry) {
111 499173 MutexLockGuard lock_guard(lock_);
112 499174 size_t idx = next_id_++ % kBufferSize;
113
2/2
✓ Branch 1 taken 115 times.
✓ Branch 2 taken 499059 times.
499174 if (idx >= buffer_.size()) {
114
1/2
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
115 buffer_.push_back(entry);
115 } else {
116
1/2
✓ Branch 2 taken 499059 times.
✗ Branch 3 not taken.
499059 buffer_[idx] = entry;
117 }
118 499174 }
119
120 6 std::vector<LogBufferEntry> GetBuffer() {
121 // Return a buffer sorted from newest to oldest buffer
122 6 std::vector<LogBufferEntry> sorted_buffer;
123 6 MutexLockGuard lock_guard(lock_);
124
2/2
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 6 times.
37 for (unsigned i = 1; i <= buffer_.size(); ++i) {
125 31 unsigned idx = (next_id_ - i) % kBufferSize;
126
1/2
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
31 sorted_buffer.push_back(buffer_[idx]);
127 }
128 12 return sorted_buffer;
129 6 }
130
131 1 void Clear() {
132 1 MutexLockGuard lock_guard(lock_);
133 1 next_id_ = 0;
134 1 buffer_.clear();
135 1 }
136
137 private:
138 static const unsigned kBufferSize = 10;
139 pthread_mutex_t lock_;
140 int next_id_;
141 std::vector<LogBufferEntry> buffer_;
142 };
143
144 LogBuffer g_log_buffer;
145
146 } // namespace
147
148 /**
149 * Sets the level that is used for all messages to the syslog facility.
150 */
151 11 void SetLogSyslogLevel(const int level) {
152
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 switch (level) {
153 case 1:
154 syslog_level = LOG_DEBUG;
155 break;
156 case 2:
157 syslog_level = LOG_INFO;
158 break;
159 11 case 3:
160 11 syslog_level = LOG_NOTICE;
161 11 break;
162 default:
163 syslog_level = LOG_NOTICE;
164 break;
165 }
166 11 }
167
168 4 int GetLogSyslogLevel() {
169
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 switch (syslog_level) {
170 case LOG_DEBUG:
171 return 1;
172 case LOG_INFO:
173 return 2;
174 4 default:
175 4 return 3;
176 }
177 }
178
179 /**
180 * Sets the syslog facility to one of local0 .. local7.
181 * Falls back to LOG_USER if local_facility is not in [0..7]
182 */
183 void SetLogSyslogFacility(const int local_facility) {
184 switch (local_facility) {
185 case 0:
186 syslog_facility = LOG_LOCAL0;
187 break;
188 case 1:
189 syslog_facility = LOG_LOCAL1;
190 break;
191 case 2:
192 syslog_facility = LOG_LOCAL2;
193 break;
194 case 3:
195 syslog_facility = LOG_LOCAL3;
196 break;
197 case 4:
198 syslog_facility = LOG_LOCAL4;
199 break;
200 case 5:
201 syslog_facility = LOG_LOCAL5;
202 break;
203 case 6:
204 syslog_facility = LOG_LOCAL6;
205 break;
206 case 7:
207 syslog_facility = LOG_LOCAL7;
208 break;
209 default:
210 syslog_facility = LOG_USER;
211 }
212 }
213
214 4 int GetLogSyslogFacility() {
215
1/9
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
4 switch (syslog_facility) {
216 case LOG_LOCAL0:
217 return 0;
218 case LOG_LOCAL1:
219 return 1;
220 case LOG_LOCAL2:
221 return 2;
222 case LOG_LOCAL3:
223 return 3;
224 case LOG_LOCAL4:
225 return 4;
226 case LOG_LOCAL5:
227 return 5;
228 case LOG_LOCAL6:
229 return 6;
230 case LOG_LOCAL7:
231 return 7;
232 4 default:
233 4 return -1;
234 }
235 }
236
237 /**
238 * The syslog prefix is used to distinguish multiple repositories in
239 * /var/log/messages
240 */
241 153 void SetLogSyslogPrefix(const std::string &prefix) {
242
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 78 times.
153 if (syslog_prefix) free(syslog_prefix);
243
244
2/2
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 79 times.
153 if (prefix == "") {
245 74 syslog_prefix = NULL;
246 } else {
247 79 unsigned len = prefix.length() + 1;
248 79 syslog_prefix = static_cast<char *>(smalloc(len));
249 79 syslog_prefix[len - 1] = '\0';
250 79 memcpy(syslog_prefix, &prefix[0], prefix.length());
251 }
252 153 }
253
254 void SetLogSyslogShowPID(bool flag) {
255 openlog(NULL, flag ? LOG_PID : 0, GetLogSyslogFacility());
256 }
257
258 /**
259 * Set the maximum verbosity level. By default kLogNormal.
260 */
261 2 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
262
263
264 1 void SetLogMicroSyslogMaxSize(unsigned bytes) {
265 1 gMicroSyslogMax = bytes;
266 1 }
267
268 /**
269 * "Micro-Syslog" write kLogSyslog messages into filename. It rotates this
270 * file. Requires for µCernVM
271 */
272 178 void SetLogMicroSyslog(const std::string &filename) {
273 178 pthread_mutex_lock(&lock_usyslock);
274
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 176 times.
178 if (usyslog_fd >= 0) {
275
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 close(usyslog_fd);
276
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 close(usyslog_fd1);
277 2 usyslog_fd = -1;
278 2 usyslog_fd1 = -1;
279 }
280
281
2/2
✓ Branch 1 taken 176 times.
✓ Branch 2 taken 2 times.
178 if (filename == "") {
282
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 174 times.
176 delete usyslog_dest;
283 176 usyslog_dest = NULL;
284 176 pthread_mutex_unlock(&lock_usyslock);
285 176 return;
286 }
287
288
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (usyslog_fd < 0) {
290 fprintf(stderr, "could not open usyslog file %s (%d), aborting\n",
291 filename.c_str(), errno);
292 abort();
293 }
294
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (usyslog_fd1 < 0) {
296 fprintf(stderr, "could not open usyslog.1 file %s.1 (%d), aborting\n",
297 filename.c_str(), errno);
298 abort();
299 }
300 platform_stat64 info;
301 2 int retval = platform_fstat(usyslog_fd, &info);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(retval == 0);
303 2 usyslog_size = info.st_size;
304
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 usyslog_dest = new string(filename);
305 2 pthread_mutex_unlock(&lock_usyslock);
306 }
307
308 50 std::string GetLogMicroSyslog() {
309 50 pthread_mutex_lock(&lock_usyslock);
310 50 string result;
311
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
50 if (usyslog_dest) result = *usyslog_dest;
312 50 pthread_mutex_unlock(&lock_usyslock);
313 50 return result;
314 }
315
316 1004 static void LogMicroSyslog(const std::string &message) {
317
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1004 times.
1004 if (message.size() == 0) return;
318
319 1004 pthread_mutex_lock(&lock_usyslock);
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1004 times.
1004 if (usyslog_fd < 0) {
321 pthread_mutex_unlock(&lock_usyslock);
322 return;
323 }
324
325 1004 int written = write(usyslog_fd, message.data(), message.size());
326
3/6
✓ Branch 0 taken 1004 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1004 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1004 times.
1004 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
327 close(usyslog_fd);
328 usyslog_fd = -1;
329 abort();
330 }
331 1004 int retval = fsync(usyslog_fd);
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1004 times.
1004 assert(retval == 0);
333 1004 usyslog_size += written;
334
335
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 995 times.
1004 if (usyslog_size >= gMicroSyslogMax) {
336 // Wipe out usyslog.1 file
337 9 retval = ftruncate(usyslog_fd1, 0);
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(retval == 0);
339
340 // Copy from usyslog to usyslog.1
341 9 retval = lseek(usyslog_fd, 0, SEEK_SET);
342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(retval == 0);
343 unsigned char buf[4096];
344 int num_bytes;
345 do {
346
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 num_bytes = read(usyslog_fd, buf, 4096);
347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(num_bytes >= 0);
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (num_bytes == 0) break;
349
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 int written = write(usyslog_fd1, buf, num_bytes);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(written == num_bytes);
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } while (num_bytes == 4096);
352 9 retval = lseek(usyslog_fd1, 0, SEEK_SET);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(retval == 0);
354
355 // Reset usyslog
356 9 retval = lseek(usyslog_fd, 0, SEEK_SET);
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(retval == 0);
358 9 retval = ftruncate(usyslog_fd, 0);
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(retval == 0);
360 9 usyslog_size = 0;
361 }
362 1004 pthread_mutex_unlock(&lock_usyslock);
363 }
364
365 /**
366 * Changes the debug log file from stderr. No effect if DEBUGMSG is undefined.
367 */
368 #ifdef DEBUGMSG
369 170 void SetLogDebugFile(const string &filename) {
370
1/2
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
170 if (filename == "") {
371
2/4
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 170 times.
170 if ((file_debug != NULL) && (file_debug != stderr)) {
372 fclose(file_debug);
373 file_debug = NULL;
374 }
375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 delete path_debug;
376 170 path_debug = NULL;
377 170 return;
378 }
379
380 if ((file_debug != NULL) && (file_debug != stderr)) {
381 if ((fclose(file_debug) < 0)) {
382 fprintf(stderr, "could not close current log file (%d), aborting\n",
383 errno);
384
385 abort();
386 }
387 }
388 int fd = open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0600);
389 if ((fd < 0) || ((file_debug = fdopen(fd, "a")) == NULL)) {
390 fprintf(stderr, "could not open debug log file %s (%d), aborting\n",
391 filename.c_str(), errno);
392 syslog(syslog_facility | LOG_ERR,
393 "could not open debug log file %s (%d), "
394 "aborting\n",
395 filename.c_str(), errno);
396 abort();
397 }
398 delete path_debug;
399 path_debug = new string(filename);
400 }
401
402 52 string GetLogDebugFile() {
403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (path_debug) return *path_debug;
404
1/2
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
52 return "";
405 }
406 #endif
407
408 34 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
409 const char *msg)) {
410 34 alt_log_func = fn;
411 34 }
412
413
414 /**
415 * Logs a message to one or multiple facilities specified by mask.
416 * Mask can be extended by a log level in the future, using the higher bits.
417 *
418 * @param[in] source Component that triggers the logging
419 * @param[in] mask Bit mask of log facilities
420 * @param[in] format Format string followed by arguments like printf
421 */
422 CVMFS_EXPORT
423 505672 void vLogCvmfs(const LogSource source, const int mask,
424 const char *format, va_list variadic_list) {
425 505672 char *msg = NULL;
426
427 // Log level check, no flag set in mask means kLogNormal
428 #ifndef DEBUGMSG
429 int log_level = mask & ((2 * kLogNone - 1) ^ (kLogLevel0 - 1));
430 if (!log_level) log_level = kLogNormal;
431 if (log_level == kLogNone) return;
432 if (log_level > max_log_level) return;
433 #endif
434
435 // Format the message string
436 505672 int retval = vasprintf(&msg, format, variadic_list);
437
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 505660 times.
505677 assert(retval != -1); // else: out of memory
438
439
2/2
✓ Branch 0 taken 6507 times.
✓ Branch 1 taken 499153 times.
505660 if (alt_log_func) {
440
1/2
✓ Branch 1 taken 6507 times.
✗ Branch 2 not taken.
6507 (*alt_log_func)(source, mask, msg);
441 6507 return;
442 }
443
444 #ifdef DEBUGMSG
445
2/2
✓ Branch 0 taken 113325 times.
✓ Branch 1 taken 385828 times.
499153 if (mask & kLogDebug) {
446 113325 pthread_mutex_lock(&lock_debug);
447
448 // Set the file pointer for debugging to stderr, if necessary
449
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 113276 times.
113325 if (file_debug == NULL) file_debug = stderr;
450
451 // Get timestamp
452 time_t rawtime;
453 113325 time(&rawtime);
454 struct tm now;
455 113325 localtime_r(&rawtime, &now);
456
457
1/2
✓ Branch 0 taken 113325 times.
✗ Branch 1 not taken.
113325 if (file_debug == stderr) pthread_mutex_lock(&lock_stderr);
458 113325 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
459 113325 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
460
1/2
✓ Branch 1 taken 113325 times.
✗ Branch 2 not taken.
113325 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
461 now.tm_zone);
462
1/2
✓ Branch 1 taken 113325 times.
✗ Branch 2 not taken.
113325 fflush(file_debug);
463
1/2
✓ Branch 0 taken 113325 times.
✗ Branch 1 not taken.
113325 if (file_debug == stderr) pthread_mutex_unlock(&lock_stderr);
464
465 113325 pthread_mutex_unlock(&lock_debug);
466 }
467 #endif
468
469
2/2
✓ Branch 0 taken 379857 times.
✓ Branch 1 taken 119296 times.
499153 if (mask & kLogStdout) {
470 379857 pthread_mutex_lock(&lock_stdout);
471
3/4
✓ Branch 0 taken 379673 times.
✓ Branch 1 taken 199 times.
✓ Branch 3 taken 379673 times.
✗ Branch 4 not taken.
379872 if (mask & kLogShowSource) printf("(%s) ", module_names[source]);
472
1/2
✓ Branch 1 taken 379872 times.
✗ Branch 2 not taken.
379872 printf("%s", msg);
473
3/4
✓ Branch 0 taken 379864 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 379864 times.
✗ Branch 4 not taken.
379872 if (!(mask & kLogNoLinebreak)) printf("\n");
474
1/2
✓ Branch 1 taken 379872 times.
✗ Branch 2 not taken.
379872 fflush(stdout);
475 379872 pthread_mutex_unlock(&lock_stdout);
476 }
477
478
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 499161 times.
499168 if (mask & kLogStderr) {
479 7 pthread_mutex_lock(&lock_stderr);
480
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
7 if (mask & kLogShowSource) fprintf(stderr, "(%s) ", module_names[source]);
481
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 fprintf(stderr, "%s", msg);
482
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
7 if (!(mask & kLogNoLinebreak)) fprintf(stderr, "\n");
483
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 fflush(stderr);
484 7 pthread_mutex_unlock(&lock_stderr);
485 }
486
487
2/2
✓ Branch 0 taken 1321 times.
✓ Branch 1 taken 497847 times.
499168 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
488
2/2
✓ Branch 0 taken 1004 times.
✓ Branch 1 taken 317 times.
1321 if (usyslog_dest) {
489
1/2
✓ Branch 2 taken 1004 times.
✗ Branch 3 not taken.
1004 string fmt_msg(msg);
490
6/10
✓ Branch 0 taken 1003 times.
✓ Branch 1 taken 1 times.
✓ Branch 4 taken 1003 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1003 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1003 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1003 times.
✗ Branch 14 not taken.
1004 if (syslog_prefix) fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
491 time_t rawtime;
492 1004 time(&rawtime);
493 char fmt_time[26];
494 1004 ctime_r(&rawtime, fmt_time);
495
3/6
✓ Branch 2 taken 1004 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1004 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1004 times.
✗ Branch 9 not taken.
1004 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
496
1/2
✓ Branch 1 taken 1004 times.
✗ Branch 2 not taken.
1004 fmt_msg.push_back('\n');
497
1/2
✓ Branch 1 taken 1004 times.
✗ Branch 2 not taken.
1004 LogMicroSyslog(fmt_msg);
498 1004 } else {
499 317 int level = syslog_level;
500
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 206 times.
317 if (mask & kLogSyslogWarn) level = LOG_WARNING;
501
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 250 times.
317 if (mask & kLogSyslogErr) level = LOG_ERR;
502
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 123 times.
317 if (syslog_prefix) {
503
1/2
✓ Branch 1 taken 194 times.
✗ Branch 2 not taken.
194 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
504 } else {
505
1/2
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
123 syslog(syslog_facility | level, "%s", msg);
506 }
507 }
508 }
509
510
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 499170 times.
499174 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
511
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 string fmt_msg(msg);
512
5/10
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
4 if (syslog_prefix) fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
513
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 if (!(mask & kLogNoLinebreak)) fmt_msg += "\n";
514
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 if (mask & kLogCustom0) LogCustom(0, fmt_msg);
515
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
4 if (mask & kLogCustom1) LogCustom(1, fmt_msg);
516
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
4 if (mask & kLogCustom2) LogCustom(2, fmt_msg);
517 4 }
518
519 // The log buffer can be read via extended attributes from cvmfs, therefore
520 // we provide an option to hide entries from the buffer if they contain
521 // sensitive information
522
2/2
✓ Branch 0 taken 499173 times.
✓ Branch 1 taken 1 times.
499174 if (!(mask & kLogSensitive))
523
3/6
✓ Branch 2 taken 499173 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 499174 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 499174 times.
✗ Branch 9 not taken.
499173 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
524
525 499175 free(msg);
526 }
527 CVMFS_EXPORT
528 505672 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
529 va_list variadic_list;
530 505672 va_start(variadic_list, format);
531
1/2
✓ Branch 1 taken 505682 times.
✗ Branch 2 not taken.
505672 vLogCvmfs(source, mask, format, variadic_list);
532 505682 va_end(variadic_list);
533 505682 }
534
535 6 std::vector<LogBufferEntry> GetLogBuffer() {
536 6 return g_log_buffer.GetBuffer();
537 }
538
539 1 void ClearLogBuffer() {
540 1 g_log_buffer.Clear();
541 1 }
542
543 5 void PrintError(const string &message) {
544 5 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
545 5 }
546
547 void PrintWarning(const string &message) {
548 LogCvmfs(kLogCvmfs, kLogStderr, "[WARNING] %s", message.c_str());
549 }
550
551
552 /**
553 * Opens a custom log file
554 */
555 18 void SetLogCustomFile(unsigned id, const std::string &filename) {
556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 assert(id < kMaxCustomlog);
557 18 pthread_mutex_lock(&customlog_locks[id]);
558
559
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
18 if (customlog_fds[id] >= 0) {
560 3 close(customlog_fds[id]);
561 3 customlog_fds[id] = -1;
562 }
563
564
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
18 if (filename.empty()) {
565
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 delete customlog_dests[id];
566 15 customlog_dests[id] = NULL;
567 15 pthread_mutex_unlock(&customlog_locks[id]);
568 15 return;
569 }
570
571 3 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (customlog_fds[id] < 0) {
573 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
574 "could not open log file %s (%d), aborting",
575 filename.c_str(), errno);
576 abort();
577 }
578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 delete customlog_dests[id];
579
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 customlog_dests[id] = new string(filename);
580
581 3 pthread_mutex_unlock(&customlog_locks[id]);
582 }
583
584
585 4 static void LogCustom(unsigned id, const std::string &message) {
586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(id < kMaxCustomlog);
587
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (message.size() == 0) return;
588
589 4 pthread_mutex_lock(&customlog_locks[id]);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(customlog_fds[id] >= 0);
591
592 4 bool retval_b = SafeWrite(customlog_fds[id], message.data(), message.size());
593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!retval_b) {
594 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
595 "could not write into log file %s (%d), aborting - lost: %s",
596 customlog_dests[id]->c_str(), errno, message.c_str());
597 abort();
598 }
599 4 int retval_i = fsync(customlog_fds[id]);
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(retval_i == 0);
601
602 4 pthread_mutex_unlock(&customlog_locks[id]);
603 }
604
605
606 5 void LogShutdown() {
607
2/4
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 SetLogMicroSyslog("");
608
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
20 for (unsigned i = 0; i < kMaxCustomlog; ++i)
609
2/4
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
15 SetLogCustomFile(i, "");
610 5 }
611
612
613 #ifdef CVMFS_NAMESPACE_GUARD
614 } // namespace CVMFS_NAMESPACE_GUARD
615 #endif
616