2323
2424#include < olp/core/logging/Configuration.h>
2525#include < olp/core/logging/FilterGroup.h>
26+ #include < olp/core/porting/optional.h>
2627#include < olp/core/thread/Atomic.h>
2728
29+ #include < algorithm>
2830#include < string>
2931#include < unordered_map>
3032
3133namespace olp {
3234namespace logging {
35+
36+ namespace {
37+ constexpr auto kSecretMask = " *****" ;
38+ const auto kSecretMaskLength = std::strlen(kSecretMask );
39+ } // namespace
40+
41+ struct LogMessageExt : public LogMessage {
42+ olp::porting::optional<std::string> adjusted_message;
43+ };
44+
3345class LogImpl {
3446 public:
3547 friend class olp ::thread::Atomic<logging::LogImpl>;
@@ -67,14 +79,21 @@ class LogImpl {
6779 unsigned int line, const char * function,
6880 const char * fullFunction);
6981
82+ void addCensor (std::string msg);
83+ void removeCensor (const std::string& msg);
84+
7085 private:
7186 LogImpl ();
7287 template <class LogItem >
7388 void appendLogItem (const LogItem& log_item);
7489
90+ template <class LogItem >
91+ void censorLogItem (LogItem& log_item, const std::string& original);
92+
7593 Configuration m_configuration;
7694 std::unordered_map<std::string, Level> m_logLevels;
7795 Level m_defaultLevel;
96+ std::vector<std::string> m_toCensor;
7897};
7998
8099LogImpl::LogImpl ()
@@ -120,7 +139,8 @@ void LogImpl::setLevel(Level level, const std::string& tag) {
120139}
121140
122141porting::optional<Level> LogImpl::getLevel (const std::string& tag) const {
123- if (tag.empty ()) return getLevel ();
142+ if (tag.empty ())
143+ return getLevel ();
124144
125145 auto foundIter = m_logLevels.find (tag);
126146 if (foundIter == m_logLevels.end ())
@@ -130,21 +150,24 @@ porting::optional<Level> LogImpl::getLevel(const std::string& tag) const {
130150}
131151
132152void LogImpl::clearLevel (const std::string& tag) {
133- if (tag.empty ()) return ;
153+ if (tag.empty ())
154+ return ;
134155
135156 m_logLevels.erase (tag);
136157}
137158
138159void LogImpl::clearLevels () { m_logLevels.clear (); }
139160
140161bool LogImpl::isEnabled (Level level) const {
141- if (level == Level::Off) return false ;
162+ if (level == Level::Off)
163+ return false ;
142164
143165 return static_cast <int >(level) >= static_cast <int >(m_defaultLevel);
144166}
145167
146168bool LogImpl::isEnabled (Level level, const std::string& tag) const {
147- if (level == Level::Off) return false ;
169+ if (level == Level::Off)
170+ return false ;
148171
149172 auto foundIter = m_logLevels.find (tag);
150173 Level targetLevel;
@@ -159,7 +182,7 @@ void LogImpl::logMessage(Level level, const std::string& tag,
159182 const std::string& message, const char * file,
160183 unsigned int line, const char * function,
161184 const char * fullFunction) {
162- LogMessage logMessage;
185+ LogMessageExt logMessage;
163186 logMessage.level = level;
164187 logMessage.tag = tag.c_str ();
165188 logMessage.message = message.c_str ();
@@ -170,6 +193,7 @@ void LogImpl::logMessage(Level level, const std::string& tag,
170193 logMessage.time = std::chrono::system_clock::now ();
171194 logMessage.threadId = getThreadId ();
172195
196+ censorLogItem (logMessage, message);
173197 appendLogItem (logMessage);
174198}
175199
@@ -181,95 +205,142 @@ void LogImpl::appendLogItem(const LogItem& log_item) {
181205 }
182206}
183207
208+ template <class LogItem >
209+ void LogImpl::censorLogItem (LogItem& log_item, const std::string& original) {
210+ bool has_copy = log_item.adjusted_message .has_value ();
211+ const std::string& src =
212+ has_copy ? log_item.adjusted_message .value () : original;
213+
214+ for (const std::string& secret : m_toCensor) {
215+ auto found_pos = src.find (secret);
216+ while (found_pos != std::string::npos) {
217+ if (!has_copy) {
218+ log_item.adjusted_message = original;
219+ has_copy = true ;
220+ log_item.message = log_item.adjusted_message .value ().c_str ();
221+ }
222+ log_item.adjusted_message .value ().replace (found_pos, secret.length (),
223+ kSecretMask );
224+ found_pos = log_item.adjusted_message .value ().find (
225+ secret, found_pos + kSecretMaskLength );
226+ }
227+ }
228+ }
229+
230+ void LogImpl::addCensor (std::string msg) {
231+ m_toCensor.emplace_back (std::move (msg));
232+ }
233+
234+ void LogImpl::removeCensor (const std::string& msg) {
235+ auto it = std::find (m_toCensor.begin (), m_toCensor.end (), msg);
236+ if (it != m_toCensor.end ()) {
237+ m_toCensor.erase (it);
238+ }
239+ }
240+
184241// implementation of public static Log API
185242// --------------------------------------------------------
186243
187244bool Log::configure (Configuration configuration) {
188- if (!LogImpl::aliveStatus ()) return false ;
245+ if (!LogImpl::aliveStatus ())
246+ return false ;
189247
190248 return LogImpl::getInstance ().locked ([&configuration](LogImpl& log) {
191249 return log.configure (std::move (configuration));
192250 });
193251}
194252
195253Configuration Log::getConfiguration () {
196- if (!LogImpl::aliveStatus ()) return Configuration ();
254+ if (!LogImpl::aliveStatus ())
255+ return Configuration ();
197256
198257 return LogImpl::getInstance ().locked (
199258 [](const LogImpl& log) { return log.getConfiguration (); });
200259}
201260
202261void Log::setLevel (Level level) {
203- if (!LogImpl::aliveStatus ()) return ;
262+ if (!LogImpl::aliveStatus ())
263+ return ;
204264
205265 LogImpl::getInstance ().locked ([level](LogImpl& log) { log.setLevel (level); });
206266}
207267
208268Level Log::getLevel () {
209- if (!LogImpl::aliveStatus ()) return Level::Off;
269+ if (!LogImpl::aliveStatus ())
270+ return Level::Off;
210271
211272 return LogImpl::getInstance ().locked (
212273 [](const LogImpl& log) { return log.getLevel (); });
213274}
214275
215276void Log::setLevel (Level level, const std::string& tag) {
216- if (!LogImpl::aliveStatus ()) return ;
277+ if (!LogImpl::aliveStatus ())
278+ return ;
217279
218280 LogImpl::getInstance ().locked (
219281 [level, &tag](LogImpl& log) { log.setLevel (level, tag); });
220282}
221283
222284void Log::setLevel (const std::string& level, const std::string& tag) {
223285 auto log_level = FilterGroup::stringToLevel (level);
224- if (!log_level) return ;
286+ if (!log_level)
287+ return ;
225288
226- if (!LogImpl::aliveStatus ()) return ;
289+ if (!LogImpl::aliveStatus ())
290+ return ;
227291
228292 LogImpl::getInstance ().locked (
229293 [&log_level, &tag](LogImpl& log) { log.setLevel (*log_level, tag); });
230294}
231295
232296porting::optional<Level> Log::getLevel (const std::string& tag) {
233- if (!LogImpl::aliveStatus ()) return porting::none;
297+ if (!LogImpl::aliveStatus ())
298+ return porting::none;
234299
235300 return LogImpl::getInstance ().locked (
236301 [&tag](const LogImpl& log) { return log.getLevel (tag); });
237302}
238303
239304void Log::clearLevel (const std::string& tag) {
240- if (!LogImpl::aliveStatus ()) return ;
305+ if (!LogImpl::aliveStatus ())
306+ return ;
241307
242308 LogImpl::getInstance ().locked ([&tag](LogImpl& log) { log.clearLevel (tag); });
243309}
244310
245311void Log::clearLevels () {
246- if (!LogImpl::aliveStatus ()) return ;
312+ if (!LogImpl::aliveStatus ())
313+ return ;
247314
248315 LogImpl::getInstance ().locked ([](LogImpl& log) { log.clearLevels (); });
249316}
250317
251318void Log::applyFilterGroup (const FilterGroup& filters) {
252- if (!LogImpl::aliveStatus ()) return ;
319+ if (!LogImpl::aliveStatus ())
320+ return ;
253321
254322 LogImpl::getInstance ().locked ([&filters](LogImpl& log) {
255323 log.clearLevels ();
256324 log.clearLevels ();
257325 auto defaultLevel = filters.getLevel ();
258- if (defaultLevel) log.setLevel (*defaultLevel);
326+ if (defaultLevel)
327+ log.setLevel (*defaultLevel);
259328 for (const auto & tagLevel : filters.m_tagLevels )
260329 log.setLevel (tagLevel.second , tagLevel.first );
261330 });
262331}
263332
264333bool Log::isEnabled (Level level) {
265- if (!LogImpl::aliveStatus ()) return false ;
334+ if (!LogImpl::aliveStatus ())
335+ return false ;
266336
267337 return LogImpl::getInstance ().locked (
268338 [level](const LogImpl& log) { return log.isEnabled (level); });
269339}
270340
271341bool Log::isEnabled (Level level, const std::string& tag) {
272- if (!LogImpl::aliveStatus ()) return false ;
342+ if (!LogImpl::aliveStatus ())
343+ return false ;
273344
274345 return LogImpl::getInstance ().locked (
275346 [level, &tag](const LogImpl& log) { return log.isEnabled (level, tag); });
@@ -279,12 +350,28 @@ void Log::logMessage(Level level, const std::string& tag,
279350 const std::string& message, const char * file,
280351 unsigned int line, const char * function,
281352 const char * fullFunction) {
282- if (!LogImpl::aliveStatus ()) return ;
353+ if (!LogImpl::aliveStatus ())
354+ return ;
283355
284356 LogImpl::getInstance ().locked ([&](LogImpl& log) {
285357 log.logMessage (level, tag, message, file, line, function, fullFunction);
286358 });
287359}
288360
361+ void Log::addCensor (const std::string& message) {
362+ if (!LogImpl::aliveStatus ())
363+ return ;
364+
365+ LogImpl::getInstance ().locked ([&](LogImpl& log) { log.addCensor (message); });
366+ }
367+
368+ void Log::removeCensor (const std::string& message) {
369+ if (!LogImpl::aliveStatus ())
370+ return ;
371+
372+ LogImpl::getInstance ().locked (
373+ [&](LogImpl& log) { log.removeCensor (message); });
374+ }
375+
289376} // namespace logging
290377} // namespace olp
0 commit comments