reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
Log.cxx
Go to the documentation of this file.
1#include "rutil/Socket.hxx"
2
3#include "rutil/ResipAssert.h"
4#include <atomic>
5#include <chrono>
6#include <iomanip>
7#include <iostream>
8#include <fstream>
9#include <stdio.h>
10#include "rutil/Data.hxx"
11
12#ifndef WIN32
13#include <sys/time.h>
14#endif
15
16#include <sys/types.h>
17#include <time.h>
18
19#include "rutil/Log.hxx"
20#include "rutil/Logger.hxx"
21#include "rutil/ParseBuffer.hxx"
22#include "rutil/ThreadIf.hxx"
23#include "rutil/Subsystem.hxx"
26
27#ifdef USE_FMT
28#include <fmt/format.h>
29#endif
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34#ifdef HAVE_VERSION_H
35#include "version.h"
36#endif
37
38using namespace resip;
39using namespace std;
40
41const Data Log::delim(" | ");
47#ifndef WIN32
48int Log::mSyslogFacility = LOG_DAEMON;
49#else
51#endif
52#define RESIP_LOG_MAX_LINE_COUNT_DEFAULT 0
53#define RESIP_LOG_MAX_BYTE_COUNT_DEFAULT 0
54unsigned int Log::MaxLineCount = RESIP_LOG_MAX_LINE_COUNT_DEFAULT; // no limit by default
55unsigned int Log::MaxByteCount = RESIP_LOG_MAX_BYTE_COUNT_DEFAULT; // no limit by default
56bool Log::KeepAllLogFiles = false; // do not keep all log files by default
57
58std::atomic<unsigned int> Log::touchCount{0};
59
60
62#ifdef LOG_ENABLE_THREAD_SETTING
63HashMap<ThreadIf::Id, std::pair<Log::ThreadSetting, bool> > Log::mThreadToLevel;
64HashMap<int, std::set<ThreadIf::Id> > Log::mServiceToThreads;
66#endif
67HashMap<int, Log::Level> Log::mServiceToLevel;
68
71
72const char
73Log::mDescriptions[][32] = {"NONE", "EMERG", "ALERT", "CRIT", "ERR", "WARNING", "NOTICE", "INFO", "DEBUG", "STACK", "CERR", ""};
74
75const char
76Log::mCEEPri[][32] = { "", "CRIT", "CRIT", "CRIT", "ERROR", "WARN", "DEBUG", "DEBUG", "DEBUG", "DEBUG", "ERROR", ""};
77
78#ifdef WIN32
79#define LOG_EMERG 0 /* system is unusable */
80#define LOG_ALERT 1 /* action must be taken immediately */
81#define LOG_CRIT 2 /* critical conditions */
82#define LOG_ERR 3 /* error conditions */
83#define LOG_WARNING 4 /* warning conditions */
84#define LOG_NOTICE 5 /* normal but significant condition */
85#define LOG_INFO 6 /* informational */
86#define LOG_DEBUG 7 /* debug-level messages */
87#endif
88const int
89Log::mSyslogPriority[] = { 0, LOG_CRIT, LOG_CRIT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_DEBUG, LOG_ERR, 0 };
90
92
93extern "C"
94{
95 void freeThreadSetting(void* setting)
96 {
97 delete static_cast<Log::ThreadSetting*>(setting);
98 }
99
100 void freeLocalLogger(void* pThreadData)
101 {
102 if (pThreadData)
103 {
104 // There was some local logger installed. Decrease its use count before we
105 // continue.
106 Log::mLocalLoggerMap.decreaseUseCount((static_cast<Log::ThreadData*>(pThreadData))->id());
107 }
108 }
109}
110
126{
127 if (--mInstanceCounter == 0)
128 {
129#ifdef LOG_ENABLE_THREAD_SETTING
131 delete Log::mLevelKey;
132#endif
133
136 }
137}
138
139void
140Log::initialize(const char* typed, const char* leveld, const char* appName, const char *logFileName, ExternalLogger* externalLogger, const char* syslogFacilityName, const char* messageStructure, const char* instanceName)
141{
142 Log::initialize(Data(typed), Data(leveld), Data(appName), logFileName, externalLogger, syslogFacilityName, Data(messageStructure), Data(instanceName));
143}
144
145void
146Log::initialize(const Data& typed, const Data& leveld, const Data& appName,
147 const char *logFileName, ExternalLogger* externalLogger,
148 const Data& syslogFacilityName,
149 const Data& messageStructure,
150 const Data& instanceName)
151{
152 Type type = Log::Cout;
153 if (isEqualNoCase(typed, "cout")) type = Log::Cout;
154 else if (isEqualNoCase(typed, "cerr")) type = Log::Cerr;
155 else if (isEqualNoCase(typed, "file")) type = Log::File;
156#ifndef WIN32
157 else type = Log::Syslog;
158#endif
159
161 level = toLevel(leveld);
162
163 MessageStructure _messageStructure = Unstructured;
164 if (isEqualNoCase(messageStructure, "JSON_CEE"))
165 {
166 _messageStructure = JSON_CEE;
167 }
168
169 Log::initialize(type, level, appName, logFileName, externalLogger, syslogFacilityName, _messageStructure, instanceName);
170}
171
172int
174{
175#ifndef WIN32
176 /* In theory, some platforms may not have all the log facilities
177 defined in syslog.h. Only LOG_USER and LOG_LOCAL[0-7] are considered
178 mandatory.
179 If the compile fails with errors in this method, then the unsupported
180 facility names could be wrapped in conditional logic.
181 */
182 if(facilityName == "LOG_AUTH")
183 {
184 return LOG_AUTH;
185 }
186 else if(facilityName == "LOG_AUTHPRIV")
187 {
188 return LOG_AUTHPRIV;
189 }
190 else if(facilityName == "LOG_CRON")
191 {
192 return LOG_CRON;
193 }
194 else if(facilityName == "LOG_DAEMON")
195 {
196 return LOG_DAEMON;
197 }
198 else if(facilityName == "LOG_FTP")
199 {
200 return LOG_FTP;
201 }
202 else if(facilityName == "LOG_KERN")
203 {
204 return LOG_KERN;
205 }
206 else if(facilityName == "LOG_LOCAL0")
207 {
208 return LOG_LOCAL0;
209 }
210 else if(facilityName == "LOG_LOCAL1")
211 {
212 return LOG_LOCAL1;
213 }
214 else if(facilityName == "LOG_LOCAL2")
215 {
216 return LOG_LOCAL2;
217 }
218 else if(facilityName == "LOG_LOCAL3")
219 {
220 return LOG_LOCAL3;
221 }
222 else if(facilityName == "LOG_LOCAL4")
223 {
224 return LOG_LOCAL4;
225 }
226 else if(facilityName == "LOG_LOCAL5")
227 {
228 return LOG_LOCAL5;
229 }
230 else if(facilityName == "LOG_LOCAL6")
231 {
232 return LOG_LOCAL6;
233 }
234 else if(facilityName == "LOG_LOCAL7")
235 {
236 return LOG_LOCAL7;
237 }
238 else if(facilityName == "LOG_LPR")
239 {
240 return LOG_LPR;
241 }
242 else if(facilityName == "LOG_MAIL")
243 {
244 return LOG_MAIL;
245 }
246 else if(facilityName == "LOG_NEWS")
247 {
248 return LOG_NEWS;
249 }
250 else if(facilityName == "LOG_SYSLOG")
251 {
252 return LOG_SYSLOG;
253 }
254 else if(facilityName == "LOG_USER")
255 {
256 return LOG_USER;
257 }
258 else if(facilityName == "LOG_UUCP")
259 {
260 return LOG_UUCP;
261 }
262#endif
263 // Nothing matched or syslog not supported on this platform
264 return -1;
265}
266
267void
268Log::initialize(Type type, Level level, const Data& appName,
269 const char * logFileName,
270 ExternalLogger* externalLogger,
271 const Data& syslogFacilityName,
272 MessageStructure messageStructure,
273 const Data& instanceName)
274{
275 {
276 Lock lock(_mutex);
278
279 mDefaultLoggerData.set(type, level, logFileName, externalLogger, messageStructure, instanceName);
280
281 ParseBuffer pb(appName);
282 pb.skipToEnd();
283#ifdef _WIN32
284 pb.skipBackToChar('\\');
285#else
286 pb.skipBackToChar('/');
287#endif
288 mAppName = pb.position();
289
290 mInstanceName = instanceName;
291
292#ifndef WIN32
293 if (!syslogFacilityName.empty())
294 {
295 mSyslogFacility = parseSyslogFacilityName(syslogFacilityName);
296 if(mSyslogFacility == -1)
297 {
298 mSyslogFacility = LOG_DAEMON;
299 if(type == Log::Syslog)
300 {
301 syslog(LOG_DAEMON | LOG_ERR, "invalid syslog facility name specified (%s), falling back to LOG_DAEMON", syslogFacilityName.c_str());
302 }
303 }
304 }
305#else
306 if (type == Syslog)
307 {
308 std::cerr << "syslog not supported on windows, using cout!" << std::endl;
309 type = Cout;
310 }
311#endif
312
313 char buffer[1024];
314 buffer[1023] = '\0';
315 if(gethostname(buffer, sizeof(buffer)) == -1)
316 {
317 mHostname = "?";
318 }
319 else
320 {
321 mHostname = buffer;
322 }
323
324#ifdef USE_FQDN_FOR_JSON_CEE_HOSTNAME
325 // Note: for Windows users, you must call initNetwork to initialize WinSock before calling
326 // Log::initialize in order for getaddrinfo to be successful
327 {
328 struct addrinfo hints;
329 struct addrinfo* info = nullptr;
330
331 memset (&hints, 0, sizeof (hints));
332 hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6 */
333 hints.ai_socktype = SOCK_STREAM;
334 hints.ai_flags = AI_CANONNAME;
335
336 if (getaddrinfo(buffer, 0, &hints, &info) == 0
337 && info != nullptr)
338 {
339 mFqdn = info->ai_canonname;
340 freeaddrinfo(info);
341 }
342 else
343 {
345 }
346 }
347#else
349#endif
350
351 }
352
353 // pre declare to prevent msvc build error C2121
354#ifdef RESIPROCATE_VERSION_STR
355#define STREAM_RESIPROCATE_VERSION_STR << RESIPROCATE_VERSION_STR
356#else
357#define STREAM_RESIPROCATE_VERSION_STR << "UNKNOWN"
358#endif // RESIPROCATE_VERSION_STR
359#ifdef ENABLE_LOG_REPOSITORY_DETAILS
360#define STREAM_ENABLE_LOG_REPOSITORY_DETAILS << " git-commit=" << RESIPROCATE_GIT_ID << " git-branch=" << RESIPROCATE_BRANCH_NAME
361#else
362#define STREAM_ENABLE_LOG_REPOSITORY_DETAILS << " git repository details unknown"
363#endif // ENABLE_LOG_REPOSITORY_DETAILS
364
367 << "logger initialized app=" << appName
368 << " version="
371 );
372
373#undef LOG_ENABLE_LOG_REPOSITORY_DETAILS
374#undef LOG_RESIPROCATE_VERSION_STR
375}
376
377void
379 Level level,
380 const Data& appName,
381 ExternalLogger& logger,
382 const Data& syslogFacilityName,
383 MessageStructure messageStructure,
384 const Data& instanceName)
385{
386 initialize(type, level, appName, 0, &logger, syslogFacilityName, messageStructure, instanceName);
387}
388
389void
390Log::initialize(const ConfigParse& configParse, const Data& appName, ExternalLogger* externalLogger)
391{
393
394 Log::setKeepAllLogFiles(configParse.getConfigBool("KeepAllLogFiles", false));
395
396 Data loggingType = configParse.getConfigData("LoggingType", "cout", true);
397 Data syslogFacilityName = configParse.getConfigData("SyslogFacility", "LOG_DAEMON", true);
398 // Most applications now use LogLevel
399 // Some applications had been using LoggingLevel, that is not deprecated
400 Data loggingLevel = configParse.getConfigData("LogLevel",
401 configParse.getConfigData("LoggingLevel", "INFO", true), true);
402 Data loggingFilename = configParse.getConfigData("LogFilename",
403 configParse.getConfigData("LoggingFilename", appName + Data(".log")), true);
404 configParse.AddBasePathIfRequired(loggingFilename);
405 Data loggingMessageStructure = configParse.getConfigData("LogMessageStructure", "Unstructured", true);
406 Data loggingInstanceName = configParse.getConfigData("LoggingInstanceName", "", true);
407
409 loggingType,
410 loggingLevel,
411 appName.c_str(),
412 loggingFilename.c_str(),
413 externalLogger,
414 syslogFacilityName,
415 loggingMessageStructure,
416 loggingInstanceName);
417
418 unsigned int loggingFileMaxLineCount = configParse.getConfigUnsignedLong("LogFileMaxLines", RESIP_LOG_MAX_LINE_COUNT_DEFAULT);
419 Log::setMaxLineCount(loggingFileMaxLineCount);
420}
421
422void
424{
425 Lock lock(_mutex);
427}
428
429void
431{
432 Lock lock(_mutex);
433 s.setLevel(level);
434}
435
436void
438{
439 if (loggerId)
440 {
441 ThreadData *pData = mLocalLoggerMap.getData(loggerId);
442 if (pData)
443 {
444 // Local logger found. Set logging level.
445 pData->mLevel = level;
446
447 // We don't need local logger instance anymore.
449 pData = NULL;
450 }
451 }
452 else
453 {
454 Lock lock(_mutex);
456 }
457}
458
461{
462 Level level;
463 ThreadData *pData;
464 if (loggerId && (pData = mLocalLoggerMap.getData(loggerId)))
465 {
466 // Local logger found. Set logging level.
467 level = pData->mLevel;
468
469 // We don't need local logger instance anymore.
471 pData = NULL;
472 }
473 else
474 {
475 Lock lock(_mutex);
477 }
478 return level;
479}
480
481void
482Log::setMaxLineCount(unsigned int maxLineCount)
483{
484 Lock lock(_mutex);
485 getLoggerData().mMaxLineCount = maxLineCount;
486}
487
488void
489Log::setMaxLineCount(unsigned int maxLineCount, Log::LocalLoggerId loggerId)
490{
491 if (loggerId)
492 {
493 ThreadData *pData = mLocalLoggerMap.getData(loggerId);
494 if (pData)
495 {
496 // Local logger found. Set logging level.
497 pData->mMaxLineCount = maxLineCount;
498
499 // We don't need local logger instance anymore.
501 pData = NULL;
502 }
503 }
504 else
505 {
506 Lock lock(_mutex);
507 mDefaultLoggerData.mMaxLineCount = maxLineCount;
508 }
509}
510
511void
512Log::setMaxByteCount(unsigned int maxByteCount)
513{
514 Lock lock(_mutex);
515 getLoggerData().mMaxByteCount = maxByteCount;
516}
517
518void
519Log::setMaxByteCount(unsigned int maxByteCount, Log::LocalLoggerId loggerId)
520{
521 if (loggerId)
522 {
523 ThreadData *pData = mLocalLoggerMap.getData(loggerId);
524 if (pData)
525 {
526 // Local logger found. Set logging level.
527 pData->mMaxByteCount = maxByteCount;
528
529 // We don't need local logger instance anymore.
531 pData = NULL;
532 }
533 }
534 else
535 {
536 Lock lock(_mutex);
537 mDefaultLoggerData.mMaxByteCount = maxByteCount;
538 }
539}
540
541void
542Log::setKeepAllLogFiles(bool keepAllLogFiles)
543{
544 Lock lock(_mutex);
545 getLoggerData().setKeepAllLogFiles(keepAllLogFiles);
546}
547
548void
549Log::setKeepAllLogFiles(bool keepAllLogFiles, Log::LocalLoggerId loggerId)
550{
551 if (loggerId)
552 {
553 ThreadData *pData = mLocalLoggerMap.getData(loggerId);
554 if (pData)
555 {
556 // Local logger found. Set logging level.
557 pData->setKeepAllLogFiles(keepAllLogFiles);
558
559 // We don't need local logger instance anymore.
561 pData = NULL;
562 }
563 }
564 else
565 {
566 Lock lock(_mutex);
567 mDefaultLoggerData.setKeepAllLogFiles(keepAllLogFiles);
568 }
569}
570
571const static Data log_("LOG_");
572
573Data
575{
576 return log_ + mDescriptions[l+1];
577}
578
581{
582 Data pri( l.prefix("LOG_") ? l.substr(4) : l);
583
584 int i=0;
585 while (strlen(mDescriptions[i]))
586 {
587 if (isEqualNoCase(pri, Data(mDescriptions[i])))
588 {
589 return Level(i-1);
590 }
591 i++;
592 }
593
594 cerr << "Choosing Debug level since string was not understood: " << l << endl;
595 return Log::Debug;
596}
597
599Log::toType(const Data& arg)
600{
601 if (arg == "cout" || arg == "COUT")
602 {
603 return Log::Cout;
604 }
605 else if (arg == "cerr" || arg == "CERR")
606 {
607 return Log::Cerr;
608 }
609 else if (arg == "file" || arg == "FILE")
610 {
611 return Log::File;
612 }
613 else
614 {
615 return Log::Syslog;
616 }
617}
618
621 const Subsystem& subsystem,
622 const char* pfile,
623 int line,
624 const char* methodName,
625 EncodeStream& strm,
626 MessageStructure messageStructure)
627{
628 char buffer[256] = "";
629 Data ts(Data::Borrow, buffer, sizeof(buffer));
630#if defined( __APPLE__ )
631 uint64_t threadId;
632 pthread_threadid_np(nullptr, &threadId);
633 const char* file = pfile;
634#elif defined( WIN32 )
635 int threadId = (int)GetCurrentThreadId();
636 const char* file = pfile + strlen(pfile);
637 while (file != pfile &&
638 *file != '\\')
639 {
640 --file;
641 }
642 if (file != pfile)
643 {
644 ++file;
645 }
646#else // #if defined( WIN32 ) || defined( __APPLE__ )
647 std::make_unsigned<pthread_t>::type threadId = pthread_self();
648 const char* file = pfile;
649#endif
650
651 switch(messageStructure)
652 {
653 case JSON_CEE:
654 {
655 auto now = std::chrono::high_resolution_clock::now();
656 std::time_t now_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
657 auto now_ns = now.time_since_epoch().count() % 1000000000;
658
659 std::tm now_tm = {};
660 // Note the argument order is intentionally reversed between the two
661#ifdef _MSC_VER
662 gmtime_s(&now_tm, &now_t);
663#else
664 gmtime_r(&now_t, &now_tm);
665#endif
666 if(resip::Log::getLoggerData().type() == Syslog)
667 {
668 strm << "@cee: ";
669 }
670 strm << "{";
671 strm << "\"hostname\":\"" << mFqdn << "\",";
672 strm << "\"pri\":\"" << mCEEPri[level+1] << "\",";
673 strm << "\"syslog\":{";
674 strm << "\"level\":" << mSyslogPriority[level+1];
675 strm << "},"; // "syslog"
676 strm << "\"time\":\"" << std::put_time(&now_tm, "%FT%T.")
677 << std::setfill('0') << std::setw(9) << now_ns << "Z" << "\",";
678 strm << "\"pname\":\"" << mAppName << "\",";
679 if(!mInstanceName.empty())
680 {
681 strm << "\"appname\":\"" << mInstanceName << "\",";
682 }
683 strm << "\"subsys\":\"" << subsystem << "\",";
684 strm << "\"proc\":{";
685#ifdef WIN32
686 strm << "\"id\":\"" << GetCurrentProcessId() << "\",";
687#else
688 strm << "\"id\":\"" << getpid() << "\",";
689#endif
690 strm << "\"tid\":" << threadId;
691 strm << "},"; // "proc"
692 strm << "\"file\":{";
693 strm << "\"name\":\"" << file << "\",";
694 strm << "\"line\":" << line;
695 strm << "},"; // "file"
696 strm << "\"native\":{";
697 strm << "\"function\":\"" << methodName << "\"";
698 strm << "},"; // "native"
699 strm << "\"msg\":\"";
700 }
701 break;
702 case Unstructured:
703 default:
704 if(resip::Log::getLoggerData().type() == Syslog)
705 {
706 strm // << mDescriptions[level+1] << Log::delim
707 // << timestamp(ts) << Log::delim
708 // << mHostname << Log::delim
709 // << mAppName << Log::delim
710 << subsystem << Log::delim
711 << "0x" << std::hex << threadId << std::dec << Log::delim
712 << file << ":" << line;
713 }
714 else
715 {
716 strm << mDescriptions[level+1] << Log::delim
717 << timestamp(ts) << Log::delim
718 << mAppName;
719 if(!mInstanceName.empty())
720 {
721 strm << '[' << mInstanceName << ']';
722 }
723 strm << Log::delim
724 << subsystem << Log::delim
725 << "0x" << std::hex << threadId << std::dec << Log::delim
726 << file << ":" << line;
727 }
728 }
729 return strm;
730}
731
732Data
734{
735 char buffer[256] = "";
736 Data result(Data::Borrow, buffer, sizeof(buffer));
737 return timestamp(result);
738}
739
740Data&
742{
743 char* datebuf = const_cast<char*>(res.data());
744 const unsigned int datebufSize = 256;
745 res.clear();
746
747#ifdef WIN32
748 int result = 1;
749 SYSTEMTIME systemTime;
750 struct { time_t tv_sec; int tv_usec; } tv = {0,0};
751 time(&tv.tv_sec);
752 GetLocalTime(&systemTime);
753 tv.tv_usec = systemTime.wMilliseconds * 1000;
754#else
755 struct timeval tv;
756 int result = gettimeofday (&tv, NULL);
757#endif
758
759 if (result == -1)
760 {
761 /* If we can't get the time of day, don't print a timestamp.
762 Under Unix, this will never happen: gettimeofday can fail only
763 if the timezone is invalid which it can't be, since it is
764 uninitialized]or if tv or tz are invalid pointers. */
765 datebuf [0] = 0;
766 }
767 else
768 {
769 /* The tv_sec field represents the number of seconds passed since
770 the Epoch, which is exactly the argument gettimeofday needs. */
771 struct tm localTimeResult = {};
772 const time_t timeInSeconds = (time_t) tv.tv_sec;
773#ifdef WIN32
774 localtime_s(&localTimeResult, &timeInSeconds); // Thread safe call on Windows
775#else
776 localtime_r(&timeInSeconds, &localTimeResult); // Thread safe version of localtime on linux
777#endif
778 strftime (datebuf,
779 datebufSize,
780 "%Y%m%d-%H%M%S", /* guaranteed to fit in 256 chars,
781 hence don't check return code */
782 &localTimeResult); // Thread safe version of localtime on linux
783 }
784
785 char msbuf[5];
786 /* Dividing (without remainder) by 1000 rounds the microseconds
787 measure to the nearest millisecond. */
788 result = snprintf(msbuf, 5, ".%3.3ld", long(tv.tv_usec / 1000));
789 if(result < 0)
790 {
791 // snprint can error (negative return code) and the compiler now generates a warning
792 // if we don't act on the return code
793 memcpy(msbuf, "0000", 5);
794 }
795
796 int datebufCharsRemaining = datebufSize - (int)strlen(datebuf);
797 snprintf(datebuf + strlen(datebuf), datebufCharsRemaining, "%s", msbuf);
798 datebuf[datebufSize - 1] = '\0'; /* Just in case strncat truncated msbuf,
799 thereby leaving its last character at
800 the end, instead of a null terminator */
801
802 // ugh, resize the Data
803 res.at((Data::size_type)strlen(datebuf)-1);
804 return res;
805}
806
809{
810 Lock lock(_mutex);
811 HashMap<int, Level>::iterator res = Log::mServiceToLevel.find(service);
812 if(res == Log::mServiceToLevel.end())
813 {
815 //default level of LOG_ERROR, but nobody uses this yet
816 Log::mServiceToLevel[service] = Err;
817 return Err;
818 }
819 return res->second;
820}
821
824{
825#ifndef LOG_ENABLE_THREAD_SETTING
826 return 0;
827#else
829 if (setting == 0)
830 {
831 return 0;
832 }
833 if (Log::touchCount.load(std::memory_order_relaxed) > 0)
834 {
835 Lock lock(_mutex);
837 HashMap<ThreadIf::Id, pair<ThreadSetting, bool> >::iterator res = Log::mThreadToLevel.find(thread);
838 resip_assert(res != Log::mThreadToLevel.end());
839 if (res->second.second)
840 {
841 setting->mLevel = res->second.first.mLevel;
842 res->second.second = false;
843 touchCount.fetch_sub(1, std::memory_order_relaxed);
844// cerr << "**Log::getThreadSetting:touchCount: " << Log::touchCount.load(std::memory_order_relaxed) << "**" << endl;
845
846 //cerr << "touchcount decremented" << endl;
847 }
848 }
849 return setting;
850#endif
851}
852
853void
858
859void
864
865void
867{
868#ifndef LOG_ENABLE_THREAD_SETTING
869 resip_assert(0);
870#else
871 //cerr << "Log::setThreadSetting: " << "service: " << info.service << " level " << toString(info.level) << " for " << pthread_self() << endl;
873 ThreadIf::tlsSetValue(*mLevelKey, (void *) new ThreadSetting(info));
874 Lock lock(_mutex);
875
876 if (Log::mThreadToLevel.find(thread) != Log::mThreadToLevel.end())
877 {
878 if (Log::mThreadToLevel[thread].second == true)
879 {
880 touchCount.fetch_sub(1, std::memory_order_relaxed);
881 }
882 }
883 Log::mThreadToLevel[thread].first = info;
884 Log::mThreadToLevel[thread].second = false;
885 Log::mServiceToThreads[info.mService].insert(thread);
886#endif
887}
888
889void
891{
892 Lock lock(_mutex);
893 Log::mServiceToLevel[service] = l;
894#ifndef LOG_ENABLE_THREAD_SETTING
895 resip_assert(0);
896#else
897 set<ThreadIf::Id>& threads = Log::mServiceToThreads[service];
898 for (set<ThreadIf::Id>::iterator i = threads.begin(); i != threads.end(); i++)
899 {
900 Log::mThreadToLevel[*i].first.mLevel = l;
901 Log::mThreadToLevel[*i].second = true;
902 }
903 Log::touchCount.fetch_add((unsigned int)threads.size(), std::memory_order_relaxed);
904#endif
905// cerr << "**Log::setServiceLevel:touchCount: " << Log::touchCount.load(std::memory_order_relaxed) << "**" << endl;
906}
907
909 Log::Level level,
910 const char * logFileName,
911 ExternalLogger* externalLogger,
912 MessageStructure messageStructure)
913{
914 return mLocalLoggerMap.create(type, level, logFileName, externalLogger, messageStructure);
915}
916
918 Log::Type type,
919 Log::Level level,
920 const char * logFileName,
921 ExternalLogger* externalLogger,
922 MessageStructure messageStructure)
923{
924 return mLocalLoggerMap.reinitialize(loggerId, type, level, logFileName, externalLogger, messageStructure);
925}
926
928{
929 return mLocalLoggerMap.remove(loggerId);
930}
931
933{
935 if (pData)
936 {
937 // There was some local logger installed. Decrease its use count before we
938 // continue.
940 pData = NULL;
941 }
942 if (loggerId)
943 {
944 pData = mLocalLoggerMap.getData(loggerId);
945 }
946 ThreadIf::tlsSetValue(*mLocalLoggerKey, (void *) pData);
947 return (loggerId == 0) || (pData != NULL)?0:1;
948}
949
950std::ostream&
951Log::Instance(unsigned int bytesToWrite)
952{
953 return getLoggerData().Instance(bytesToWrite);
954}
955
956void
958{
960}
961
962#ifndef WIN32
963void
964Log::droppingPrivileges(uid_t uid, pid_t pid)
965{
967}
968#endif
969
970bool
972{
973 if (sub.getLevel() != Log::None)
974 {
975 return level <= sub.getLevel();
976 }
977 else
978 {
979 return (level <= Log::getLoggerData().mLevel);
980 }
981}
982
983void
985{
986#ifdef WIN32
987 const char *text = result.c_str();
988#ifdef UNDER_CE
989 LPWSTR lpwstrText = resip::ToWString(text);
990 OutputDebugStringW(lpwstrText);
991 FreeWString(lpwstrText);
992#else
993 OutputDebugStringA(text);
994#endif
995#endif
996}
997
999 Log::Level level,
1000 const char * logFileName,
1001 ExternalLogger* externalLogger,
1002 MessageStructure messageStructure)
1003{
1006 Log::ThreadData *pNewData = new Log::ThreadData(id, type, level, logFileName,
1007 externalLogger, messageStructure);
1008 mLoggerInstancesMap[id].first = pNewData;
1009 mLoggerInstancesMap[id].second = 0;
1010 return id;
1011}
1012
1014 Log::Type type,
1016 const char * logFileName,
1017 ExternalLogger* externalLogger,
1018 MessageStructure messageStructure)
1019{
1020 Lock lock(mLoggerInstancesMapMutex);
1021 LoggerInstanceMap::iterator it = mLoggerInstancesMap.find(loggerId);
1022 if (it == mLoggerInstancesMap.end())
1023 {
1024 // No such logger ID
1025 std::cerr << "Log::LocalLoggerMap::remove(): Unknown local logger id=" << loggerId << std::endl;
1026 return 1;
1027 }
1028 it->second.first->reset();
1029 it->second.first->set(type, level, logFileName, externalLogger, messageStructure);
1030 return 0;
1031}
1032
1034{
1035 Lock lock(mLoggerInstancesMapMutex);
1036 LoggerInstanceMap::iterator it = mLoggerInstancesMap.find(loggerId);
1037 if (it == mLoggerInstancesMap.end())
1038 {
1039 // No such logger ID
1040 std::cerr << "Log::LocalLoggerMap::remove(): Unknown local logger id=" << loggerId << std::endl;
1041 return 1;
1042 }
1043 if (it->second.second > 0)
1044 {
1045 // Non-zero use-count.
1046 std::cerr << "Log::LocalLoggerMap::remove(): Use count is non-zero (" << it->second.second << ")!" << std::endl;
1047 return 2;
1048 }
1049 delete it->second.first; // delete ThreadData
1050 mLoggerInstancesMap.erase(it);
1051 return 0;
1052}
1053
1055{
1056 Lock lock(mLoggerInstancesMapMutex);
1057 LoggerInstanceMap::iterator it = mLoggerInstancesMap.find(loggerId);
1058 if (it == mLoggerInstancesMap.end())
1059 {
1060 // No such logger ID
1061 return NULL;
1062 }
1063 it->second.second++;
1064 return it->second.first;
1065}
1066
1068{
1069 Lock lock(mLoggerInstancesMapMutex);
1070 LoggerInstanceMap::iterator it = mLoggerInstancesMap.find(loggerId);
1071 if (it != mLoggerInstancesMap.end())
1072 {
1073 it->second.second--;
1074 resip_assert(it->second.second >= 0);
1075 }
1076}
1077
1078
1080 const resip::Subsystem& subsystem,
1081 const char* file,
1082 int line,
1083 const char* methodName) :
1084 mLevel(level),
1085 mSubsystem(subsystem),
1086 mFile(file),
1087 mLine(line),
1088 mMethodName(methodName),
1089 mData(Data::Borrow, mBuffer, sizeof(mBuffer)),
1090 mStream(mData.clear())
1091{
1092
1094 {
1096 if(messageStructure == Unstructured)
1097 {
1098 Log::tags(mLevel, mSubsystem, mFile, mLine, mMethodName, mStream, messageStructure);
1099 mStream << resip::Log::delim;
1100 mStream.flush();
1101 }
1102
1103 mHeaderLength = mData.size();
1104 }
1105 else
1106 {
1107 mHeaderLength = 0;
1108 }
1109}
1110
1112{
1114 if(messageStructure == JSON_CEE)
1115 {
1116 mStream.flush();
1117 Data msg;
1118 oDataStream o(msg);
1119 // add the JSON message attributes
1120 Log::tags(mLevel, mSubsystem, mFile, mLine, mMethodName, o, messageStructure);
1121
1122 // JSON encode the message body
1123 // FIXME - this could be done on the fly in DataStream
1124
1125 static const char *json_special = "\"\\/\b\f\n\r\t";
1126 static const char *json_special_replace = "\"\\/bfnrt";
1127 const char* _data = mData.data();
1128 for(Data::size_type i = 0; i < mData.size(); i++)
1129 {
1130 const char& c = _data[i];
1131 const char *special = strchr (json_special, c);
1132 if (special != NULL)
1133 {
1134 const char *replace = json_special_replace + (special - json_special);
1135 o << '\\' << *replace;
1136 }
1137 else if (c < 0x20)
1138 {
1139 /* Everything below 0x20 must be escaped */
1140 o << "\\u00" << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)c;
1141 }
1142 else
1143 {
1144 o << _data[i];
1145 }
1146 }
1147 // add the trailing JSON
1148 o << "\"}";
1149 o.flush();
1150
1151 mData.takeBuf(msg);
1152 }
1153
1154 mStream.flush();
1155
1157 {
1159 mData.data() + mHeaderLength,
1160 (int)mData.size() - mHeaderLength);
1161 if (!(*resip::Log::getExternal())(mLevel,
1162 mSubsystem,
1164 mFile,
1165 mLine,
1166 rest,
1167 mData,
1169 {
1170 return;
1171 }
1172 }
1173
1175
1176 if(logType == resip::Log::OnlyExternal ||
1178 {
1179 return;
1180 }
1181
1183 // !dlb! implement VSDebugWindow as an external logger
1184 if (logType == resip::Log::VSDebugWindow)
1185 {
1186 mData += "\r\n";
1188 }
1189 else
1190 {
1191 // endl is magic in syslog -- so put it here
1192 std::ostream& _instance = Instance((int)mData.size()+2);
1193 if (logType == resip::Log::Syslog)
1194 {
1195 _instance << mLevel;
1196 }
1197 _instance << mData << std::endl;
1198 }
1199}
1200
1201std::ostream&
1202Log::ThreadData::Instance(unsigned int bytesToWrite)
1203{
1204// std::cerr << "Log::ThreadData::Instance() id=" << mId << " type=" << mType << std::endl;
1205 switch (mType)
1206 {
1207 case Log::Syslog:
1208 if (mLogger == 0)
1209 {
1210 mLogger = new SysLogStream(mAppName, mSyslogFacility);
1211 }
1212 return *mLogger;
1213
1214 case Log::Cerr:
1215 return std::cerr;
1216
1217 case Log::Cout:
1218 return std::cout;
1219
1220 case Log::File:
1221 if (mLogger == 0 ||
1222 (maxLineCount() && mLineCount >= maxLineCount()) ||
1223 (maxByteCount() && ((unsigned int)mLogger->tellp() + bytesToWrite) >= maxByteCount()))
1224 {
1225 Data logFileName(mLogFileName != "" ? mLogFileName : "resiprocate.log");
1226 if (mLogger)
1227 {
1228 if (keepAllLogFiles())
1229 {
1230 char buffer[256];
1231 Data ts(Data::Borrow, buffer, sizeof(buffer));
1232 Data oldLogFileName(logFileName + "_" + timestamp(ts));
1233
1234 delete mLogger;
1235
1236 // Keep all log files, rename the log file with timestamp
1237 rename(logFileName.c_str(), oldLogFileName.c_str());
1238 }
1239 else
1240 {
1241 Data oldLogFileName(logFileName + ".old");
1242 delete mLogger;
1243 // Keep one backup file: Delete .old file, Rename log file to .old
1244 // Could be expanded in the future to keep X backup log files
1245 remove(oldLogFileName.c_str());
1246 rename(logFileName.c_str(), oldLogFileName.c_str());
1247 }
1248 }
1249 mLogger = new std::ofstream(logFileName.c_str(), std::ios_base::out | std::ios_base::app);
1250 mLineCount = 0;
1251 }
1252 mLineCount++;
1253 return *mLogger;
1254 default:
1255 resip_assert(0);
1256 return std::cout;
1257 }
1258}
1259
1260void
1262 const char* logFileName,
1263 ExternalLogger* pExternalLogger,
1264 MessageStructure messageStructure,
1265 const Data& instanceName)
1266{
1267 mType = type;
1268 mLevel = level;
1269
1270 if (logFileName)
1271 {
1272#ifdef USE_FMT
1273 fmt::memory_buffer _loggingFilename;
1274 fmt::format_to(std::back_inserter(_loggingFilename),
1275 logFileName,
1276#ifdef WIN32
1277 fmt::arg("pid", (int)GetCurrentProcess()),
1278#else
1279 fmt::arg("pid", getpid()),
1280#endif
1281 fmt::arg("timestamp", time(0)));
1282 mLogFileName = Data(_loggingFilename.data(), _loggingFilename.size());
1283#else
1284 mLogFileName = logFileName;
1285 mLogFileName.replace("{timestamp}", Data((uint64_t)time(0)));
1286#ifdef WIN32
1287 mLogFileName.replace("{pid}", Data((uint64_t)GetCurrentProcess()));
1288#else
1289 mLogFileName.replace("{pid}", Data(getpid()));
1290#endif
1291#endif
1292 }
1293 else
1294 {
1295 mLogFileName.clear();
1296 }
1297 mExternalLogger = pExternalLogger;
1298 mMessageStructure = messageStructure;
1299 mInstanceName = instanceName;
1300}
1301
1302void
1304{
1305 delete mLogger;
1306 mLogger = NULL;
1307}
1308
1309#ifndef WIN32
1310void
1312{
1313 if(mType == Log::File)
1314 {
1315 Data logFileName(mLogFileName != "" ? mLogFileName : "resiprocate.log");
1316 if(chown(logFileName.c_str(), uid, pid) < 0)
1317 {
1318 // Some error occurred
1319 std::cerr << "ERROR: chown failed on " << logFileName << std::endl;
1320 }
1321 }
1322}
1323#endif
1324
1325/* ====================================================================
1326 * The Vovida Software License, Version 1.0
1327 *
1328 * Copyright (c) 2000-2005
1329 *
1330 * Redistribution and use in source and binary forms, with or without
1331 * modification, are permitted provided that the following conditions
1332 * are met:
1333 *
1334 * 1. Redistributions of source code must retain the above copyright
1335 * notice, this list of conditions and the following disclaimer.
1336 *
1337 * 2. Redistributions in binary form must reproduce the above copyright
1338 * notice, this list of conditions and the following disclaimer in
1339 * the documentation and/or other materials provided with the
1340 * distribution.
1341 *
1342 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1343 * and "Vovida Open Communication Application Library (VOCAL)" must
1344 * not be used to endorse or promote products derived from this
1345 * software without prior written permission. For written
1346 * permission, please contact vocal@vovida.org.
1347 *
1348 * 4. Products derived from this software may not be called "VOCAL", nor
1349 * may "VOCAL" appear in their name, without prior written
1350 * permission of Vovida Networks, Inc.
1351 *
1352 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1353 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1354 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1355 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1356 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1357 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1358 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1359 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1360 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1361 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1362 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1363 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1364 * DAMAGE.
1365 *
1366 * ====================================================================
1367 *
1368 * This software consists of voluntary contributions made by Vovida
1369 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1370 * Inc. For more information on Vovida Networks, Inc., please see
1371 * <http://www.vovida.org/>.
1372 *
1373 */
#define STREAM_RESIPROCATE_VERSION_STR
void freeLocalLogger(void *pThreadData)
Definition Log.cxx:100
#define RESIP_LOG_MAX_BYTE_COUNT_DEFAULT
Definition Log.cxx:53
static const Data log_("LOG_")
#define STREAM_ENABLE_LOG_REPOSITORY_DETAILS
void freeThreadSetting(void *setting)
Definition Log.cxx:95
#define RESIP_LOG_MAX_LINE_COUNT_DEFAULT
Definition Log.cxx:52
#define GenericLog(system_, level_, args_)
Definition Logger.hxx:150
#define resip_assert(x)
This file needs to work for both C and C++ code.
static ServerProcess * _instance
Handles cross-platform sockets compatibility.
bool AddBasePathIfRequired(Data &filename) const
resip::Data getConfigData(const resip::Data &name, const resip::Data &defaultValue, bool useDefaultIfEmpty=false) const
unsigned long getConfigUnsignedLong(const resip::Data &name, unsigned long defaultValue) const
bool getConfigBool(const resip::Data &name, bool defaultValue) const
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
@ Share
The Data instance will use the buffer in a read-only mode.
Definition Data.hxx:266
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Definition Data.hxx:260
char & at(size_type p)
Returns the character at the specified position.
Definition Data.cxx:988
bool prefix(const Data &pre) const noexcept
Returns true if this Data starts with the bytes indicated by the passed-in Data.
Definition Data.cxx:1888
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
Definition Data.cxx:1932
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
size_t size_type
Definition Data.hxx:94
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
Data & clear()
Clears the contents of this Data.
Definition Data.hxx:800
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
Interface functor for external logging.
Definition Log.hxx:448
static unsigned int mInstanceCounter
Definition Log.hxx:468
Guard(Level level, const Subsystem &system, const char *file, int line, const char *methodName)
Remember the logging values and be a a stream to receive the log contents.
Definition Log.cxx:1079
~Guard()
Commit logging.
Definition Log.cxx:1111
Thread Local logger settings storage.
Definition Log.hxx:382
int reinitialize(LocalLoggerId loggerId, Type type, Level level, const char *logFileName=NULL, ExternalLogger *externalLogger=NULL, MessageStructure messageStructure=Unstructured)
Reinitialize all new setting for a local logger instance.
Definition Log.cxx:1013
int remove(LocalLoggerId loggerId)
Remove existing logger instance from map and destroy.
Definition Log.cxx:1033
Mutex mLoggerInstancesMapMutex
Mutex to synchronize access to Thread Local logger settings storage.
Definition Log.hxx:427
LocalLoggerId create(Type type, Level level, const char *logFileName=NULL, ExternalLogger *externalLogger=NULL, MessageStructure messageStructure=Unstructured)
Create new logger instance and return its ID (zero on error)
Definition Log.cxx:998
LocalLoggerId mLastLocalLoggerId
Last used LocalLoggerId.
Definition Log.hxx:425
void decreaseUseCount(LocalLoggerId loggerId)
Decrease use counter for given loggerId.
Definition Log.cxx:1067
LoggerInstanceMap mLoggerInstancesMap
Definition Log.hxx:423
ThreadData * getData(LocalLoggerId loggerId)
Get pointer to ThreadData for given ID and increase use counter.
Definition Log.cxx:1054
volatile MessageStructure mMessageStructure
Definition Log.hxx:350
volatile Level mLevel
Definition Log.hxx:344
std::ostream & Instance(unsigned int bytesToWrite)
Return logger stream instance, creating it if needed.
Definition Log.cxx:1202
void droppingPrivileges(uid_t uid, pid_t pid)
Definition Log.cxx:1311
LocalLoggerId id() const
Definition Log.hxx:331
void set(Type type=Cout, Level level=Info, const char *logFileName=NULL, ExternalLogger *pExternalLogger=NULL, MessageStructure messageStructure=Unstructured, const Data &instanceName="")
Definition Log.cxx:1261
void setKeepAllLogFiles(bool keepAllLogFiles)
Definition Log.hxx:337
volatile unsigned int mMaxByteCount
Definition Log.hxx:346
void reset()
Frees logger stream.
Definition Log.cxx:1303
volatile unsigned int mMaxLineCount
Definition Log.hxx:345
static bool isLogging(Log::Level level, const Subsystem &)
Definition Log.cxx:971
static const int mSyslogPriority[]
Definition Log.hxx:371
static HashMap< ThreadIf::Id, std::pair< ThreadSetting, bool > > mThreadToLevel
DEPRECATED! Left for backward compatibility - use localLoggers instead.
Definition Log.hxx:438
static ExternalLogger * getExternal()
Definition Log.hxx:164
static ThreadData & getLoggerData()
Definition Log.hxx:374
static void setMaxByteCount(unsigned int maxByteCount)
Definition Log.cxx:512
@ Syslog
Definition Log.hxx:56
@ OnlyExternal
log messages are only written to external logger
Definition Log.hxx:60
@ VSDebugWindow
Use only for Visual Studio Debug Window logging - WIN32 must be defined.
Definition Log.hxx:59
@ OnlyExternalNoHeaders
same as OnlyExternal, only the messageWithHeaders param of the ExternalLogger will be empty.
Definition Log.hxx:61
static const char mCEEPri[][32]
Definition Log.hxx:370
static Data mInstanceName
Definition Log.hxx:372
static int mSyslogFacility
Definition Log.hxx:368
static const ThreadSetting * getThreadSetting()
DEPRECATED! Left for backward compatibility - use localLoggers instead.
Definition Log.cxx:823
static ThreadData mDefaultLoggerData
Default logger settings.
Definition Log.hxx:364
static int parseSyslogFacilityName(const Data &facilityName)
Definition Log.cxx:173
static void reset()
Frees logger stream.
Definition Log.cxx:957
static Data toString(Level l)
Definition Log.cxx:574
static Level getServiceLevel(int service)
Definition Log.cxx:808
static unsigned int MaxLineCount
Definition Log.hxx:293
static Data mFqdn
Definition Log.hxx:367
static void setServiceLevel(int service, Level l)
DEPRECATED! Left for backward compatibility - use localLoggers instead.
Definition Log.cxx:890
static Data timestamp()
Definition Log.cxx:733
static int setThreadLocalLogger(LocalLoggerId loggerId)
Set logger instance with given ID as a thread local logger.
Definition Log.cxx:932
static LocalLoggerMap mLocalLoggerMap
Definition Log.hxx:432
int LocalLoggerId
Thread Local logger ID type.
Definition Log.hxx:98
static Data getAppName()
Definition Log.hxx:168
static std::atomic< unsigned int > touchCount
Definition Log.hxx:290
static Level toLevel(const Data &l)
Definition Log.cxx:580
static HashMap< int, Level > mServiceToLevel
DEPRECATED! Left for backward compatibility - use localLoggers instead.
Definition Log.hxx:442
static void setThreadSetting(ThreadSetting info)
Definition Log.cxx:866
static ThreadIf::TlsKey * mLocalLoggerKey
Definition Log.hxx:433
static void setLevel(Level level)
Set logging level for current thread.
Definition Log.cxx:423
static int localLoggerReinitialize(LocalLoggerId loggerId, Type type, Level level, const char *logFileName=NULL, ExternalLogger *externalLogger=NULL, MessageStructure messageStructure=Unstructured)
Reinitialize all new setting for a local logger instance.
Definition Log.cxx:917
static unsigned int MaxByteCount
Definition Log.hxx:294
static EncodeStream & tags(Log::Level level, const Subsystem &subsystem, const char *file, int line, const char *methodName, EncodeStream &strm, MessageStructure messageStructure)
output the loglevel, hostname, appname, pid, tid, subsystem
Definition Log.cxx:620
static HashMap< int, std::set< ThreadIf::Id > > mServiceToThreads
Definition Log.hxx:439
static int localLoggerRemove(LocalLoggerId loggerId)
Destroy existing logger instance.
Definition Log.cxx:927
static Mutex _mutex
Definition Log.hxx:289
static Data mAppName
Definition Log.hxx:365
static const Data delim
Definition Log.hxx:291
static Level level()
Return logging level for current thread.
Definition Log.hxx:221
static void setKeepAllLogFiles(bool keepAllLogFiles)
Definition Log.cxx:542
static void setMaxLineCount(unsigned int maxLineCount)
Definition Log.cxx:482
static LocalLoggerId id()
Definition Log.hxx:224
static void droppingPrivileges(uid_t uid, pid_t pid)
Definition Log.cxx:964
static bool KeepAllLogFiles
Definition Log.hxx:295
@ Debug
Definition Log.hxx:84
MessageStructure
Definition Log.hxx:92
@ JSON_CEE
Definition Log.hxx:94
@ Unstructured
Definition Log.hxx:93
static const char mDescriptions[][32]
Definition Log.hxx:369
static Data mHostname
Definition Log.hxx:366
static void initialize(Type type, Level level, const Data &appName, const char *logFileName=0, ExternalLogger *externalLogger=0, const Data &syslogFacility="LOG_DAEMON", MessageStructure messageStructure=Unstructured, const Data &instanceName="")
Definition Log.cxx:268
static void OutputToWin32DebugWindow(const Data &result)
Definition Log.cxx:984
static Type toType(const Data &t)
Definition Log.cxx:599
static ThreadIf::TlsKey * mLevelKey
Definition Log.hxx:440
static std::ostream & Instance(unsigned int bytesToWrite)
Definition Log.cxx:951
static LocalLoggerId localLoggerCreate(Type type, Level level, const char *logFileName=NULL, ExternalLogger *externalLogger=NULL, MessageStructure messageStructure=Unstructured)
Create new logger instance and return its ID (zero on error)
Definition Log.cxx:908
Provides string-parsing functionality with protection from buffer overflow.
const char * skipBackToChar(char c)
CurrentPosition skipToEnd()
CurrentPosition position() const
Class used to specify what sub-system given sections of code belong to, for use by the logging system...
Definition Subsystem.hxx:34
void setLevel(Log::Level level)
Definition Subsystem.hxx:57
static Subsystem NONE
Definition Subsystem.hxx:43
Log::Level getLevel() const
Definition Subsystem.hxx:56
static void * tlsGetValue(TlsKey key)
This function follows pthread_getspecific() signature.
Definition ThreadIf.cxx:179
static int tlsKeyCreate(TlsKey &key, TlsDestructor *destructor)
This function follows pthread_key_create() signature.
Definition ThreadIf.cxx:130
pthread_key_t TlsKey
Definition ThreadIf.hxx:85
static Id selfId()
Definition ThreadIf.cxx:124
static int tlsKeyDelete(TlsKey key)
This function follows pthread_key_delete() signature.
Definition ThreadIf.cxx:150
static int tlsSetValue(TlsKey key, const void *val)
This function follows pthread_setspecific() signature.
Definition ThreadIf.cxx:169
std::thread::id Id
Definition ThreadIf.hxx:79
An ostream that operates on an existing Data.
dcm! – add UnusedChecking(_enum) below;
std::mutex Mutex
A semaphore that can be locked by only one thread at a time.
Definition Mutex.hxx:37
bool isEqualNoCase(const Data &left, const Data &right)
Definition Data.hxx:1116
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
Definition Lock.hxx:28
unsigned long long uint64_t
Definition Stun.hxx:39
#define EncodeStream
void remove(char *pAor)
Definition userAdmin.cxx:35