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
2829#include < string>
2930#include < unordered_map>
3031
3132namespace olp {
3233namespace logging {
34+
35+ namespace {
36+
37+ constexpr auto kSecretMask = " *****" ;
38+ }
39+
40+ struct LogMessageEx : public LogMessage {
41+ olp::porting::optional<std::string> adjusted_message;
42+ };
43+
3344class LogImpl {
3445 public:
3546 friend class olp ::thread::Atomic<logging::LogImpl>;
@@ -67,14 +78,20 @@ class LogImpl {
6778 unsigned int line, const char * function,
6879 const char * fullFunction);
6980
81+ void censor (std::string msg);
82+
7083 private:
7184 LogImpl ();
7285 template <class LogItem >
7386 void appendLogItem (const LogItem& log_item);
7487
88+ template <class LogItem >
89+ void censorLogItem (LogItem& log_item, const std::string& original);
90+
7591 Configuration m_configuration;
7692 std::unordered_map<std::string, Level> m_logLevels;
7793 Level m_defaultLevel;
94+ std::vector<std::string> m_toCensor;
7895};
7996
8097LogImpl::LogImpl ()
@@ -159,7 +176,7 @@ void LogImpl::logMessage(Level level, const std::string& tag,
159176 const std::string& message, const char * file,
160177 unsigned int line, const char * function,
161178 const char * fullFunction) {
162- LogMessage logMessage;
179+ LogMessageEx logMessage;
163180 logMessage.level = level;
164181 logMessage.tag = tag.c_str ();
165182 logMessage.message = message.c_str ();
@@ -170,6 +187,7 @@ void LogImpl::logMessage(Level level, const std::string& tag,
170187 logMessage.time = std::chrono::system_clock::now ();
171188 logMessage.threadId = getThreadId ();
172189
190+ censorLogItem (logMessage, message);
173191 appendLogItem (logMessage);
174192}
175193
@@ -181,6 +199,31 @@ void LogImpl::appendLogItem(const LogItem& log_item) {
181199 }
182200}
183201
202+ template <class LogItem >
203+ void LogImpl::censorLogItem (LogItem& log_item, const std::string& original) {
204+ bool has_copy = log_item.adjusted_message .has_value ();
205+ const std::string& src =
206+ has_copy ? log_item.adjusted_message .value () : original;
207+
208+ for (const std::string& secret : m_toCensor) {
209+ auto found_pos = src.find (secret);
210+ while (found_pos != std::string::npos) {
211+ if (!has_copy) {
212+ log_item.adjusted_message = original;
213+ has_copy = true ;
214+ log_item.message = log_item.adjusted_message .value ().c_str ();
215+ }
216+ log_item.adjusted_message .value ().replace (found_pos, secret.length (),
217+ kSecretMask );
218+ found_pos = log_item.adjusted_message .value ().find (secret, found_pos);
219+ }
220+ }
221+ }
222+
223+ void LogImpl::censor (std::string msg) {
224+ m_toCensor.emplace_back (std::move (msg));
225+ }
226+
184227// implementation of public static Log API
185228// --------------------------------------------------------
186229
@@ -286,5 +329,12 @@ void Log::logMessage(Level level, const std::string& tag,
286329 });
287330}
288331
332+ void Log::censor (const std::string& message) {
333+ if (!LogImpl::aliveStatus ())
334+ return ;
335+
336+ LogImpl::getInstance ().locked ([&](LogImpl& log) { log.censor (message); });
337+ }
338+
289339} // namespace logging
290340} // namespace olp
0 commit comments