1 // Module:  Log4CPLUS
2 // File:    loglog.cxx
3 // Created: 6/2001
4 // Author:  Tad E. Smith
5 //
6 //
7 // Copyright 2001-2013 Tad E. Smith
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 //
13 //     http://www.apache.org/licenses/LICENSE-2.0
14 //
15 // Unless required by applicable law or agreed to in writing, software
16 // distributed under the License is distributed on an "AS IS" BASIS,
17 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 // See the License for the specific language governing permissions and
19 // limitations under the License.
20 
21 #include <log4cplus/streams.h>
22 #include <log4cplus/helpers/loglog.h>
23 #include <log4cplus/thread/syncprims-pub-impl.h>
24 #include <log4cplus/thread/threads.h>
25 #include <log4cplus/internal/env.h>
26 #include <log4cplus/consoleappender.h>
27 #include <ostream>
28 #include <stdexcept>
29 
30 
31 namespace log4cplus { namespace helpers {
32 
33 namespace
34 {
35 
36 static tchar const PREFIX[] = LOG4CPLUS_TEXT("log4cplus: ");
37 static tchar const WARN_PREFIX[] = LOG4CPLUS_TEXT("log4cplus:WARN ");
38 static tchar const ERR_PREFIX[] = LOG4CPLUS_TEXT("log4cplus:ERROR ");
39 
40 } // namespace
41 
42 
43 LogLog *
getLogLog()44 LogLog::getLogLog()
45 {
46     return &helpers::getLogLog ();
47 }
48 
49 
LogLog()50 LogLog::LogLog()
51     : debugEnabled(TriUndef)
52     , quietMode(TriUndef)
53 { }
54 
55 
~LogLog()56 LogLog::~LogLog()
57 { }
58 
59 
60 void
setInternalDebugging(bool enabled)61 LogLog::setInternalDebugging(bool enabled)
62 {
63     thread::MutexGuard guard (mutex);
64 
65     debugEnabled = enabled ? TriTrue : TriFalse;
66 }
67 
68 
69 void
setQuietMode(bool quietModeVal)70 LogLog::setQuietMode(bool quietModeVal)
71 {
72     thread::MutexGuard guard (mutex);
73 
74     quietMode = quietModeVal ? TriTrue : TriFalse;
75 }
76 
77 
78 void
debug(const log4cplus::tstring & msg) const79 LogLog::debug(const log4cplus::tstring& msg) const
80 {
81     logging_worker (tcout, &LogLog::get_debug_mode, PREFIX, msg);
82 }
83 
84 
85 void
debug(tchar const * msg) const86 LogLog::debug(tchar const * msg) const
87 {
88     logging_worker (tcout, &LogLog::get_debug_mode, PREFIX, msg);
89 }
90 
91 
92 void
warn(const log4cplus::tstring & msg) const93 LogLog::warn(const log4cplus::tstring& msg) const
94 {
95     logging_worker (tcerr, &LogLog::get_not_quiet_mode, WARN_PREFIX, msg);
96 }
97 
98 
99 void
warn(tchar const * msg) const100 LogLog::warn(tchar const * msg) const
101 {
102     logging_worker (tcerr, &LogLog::get_not_quiet_mode, WARN_PREFIX, msg);
103 }
104 
105 
106 void
error(const log4cplus::tstring & msg,bool throw_flag) const107 LogLog::error(const log4cplus::tstring& msg, bool throw_flag) const
108 {
109     logging_worker (tcerr, &LogLog::get_not_quiet_mode, ERR_PREFIX, msg,
110         throw_flag);
111 }
112 
113 
114 void
error(tchar const * msg,bool throw_flag) const115 LogLog::error(tchar const * msg, bool throw_flag) const
116 {
117     logging_worker (tcerr, &LogLog::get_not_quiet_mode, ERR_PREFIX, msg,
118         throw_flag);
119 }
120 
121 
122 bool
get_quiet_mode() const123 LogLog::get_quiet_mode () const
124 {
125     if (quietMode == TriUndef)
126         set_tristate_from_env (&quietMode,
127             LOG4CPLUS_TEXT ("LOG4CPLUS_LOGLOG_QUIETMODE"));
128 
129     return quietMode == TriTrue;
130 }
131 
132 
133 bool
get_not_quiet_mode() const134 LogLog::get_not_quiet_mode () const
135 {
136     return ! get_quiet_mode ();
137 }
138 
139 
140 bool
get_debug_mode() const141 LogLog::get_debug_mode () const
142 {
143     if (debugEnabled == TriUndef)
144         set_tristate_from_env (&debugEnabled,
145             LOG4CPLUS_TEXT ("LOG4CPLUS_LOGLOG_DEBUGENABLED"));
146 
147     return debugEnabled && ! get_quiet_mode ();
148 }
149 
150 
151 void
set_tristate_from_env(TriState * result,tchar const * envvar_name)152 LogLog::set_tristate_from_env (TriState * result, tchar const * envvar_name)
153 {
154     tstring envvar_value;
155     bool exists = internal::get_env_var (envvar_value, envvar_name);
156     bool value = false;
157     if (exists && internal::parse_bool (value, envvar_value) && value)
158         *result = TriTrue;
159     else
160         *result = TriFalse;
161 }
162 
163 
164 template <typename StringType>
165 void
logging_worker(tostream & os,bool (LogLog::* cond)()const,tchar const * prefix,StringType const & msg,bool throw_flag) const166 LogLog::logging_worker (tostream & os, bool (LogLog:: * cond) () const,
167     tchar const * prefix, StringType const & msg, bool throw_flag) const
168 {
169     bool output;
170     {
171         thread::MutexGuard guard (mutex);
172         output = (this->*cond) ();
173     }
174 
175     if (LOG4CPLUS_UNLIKELY (output))
176     {
177         // XXX This is potential recursive lock of
178         // ConsoleAppender::outputMutex.
179         thread::MutexGuard outputGuard (ConsoleAppender::getOutputMutex ());
180         os << prefix << msg << std::endl;
181     }
182 
183     if (LOG4CPLUS_UNLIKELY (throw_flag))
184         throw std::runtime_error (LOG4CPLUS_TSTRING_TO_STRING (msg));
185 }
186 
187 
188 } } // namespace log4cplus { namespace helpers {
189