Skip to content

Commit 766d495

Browse files
Add censor API to Log (#1639)
* Add censor API to Log It allows to set values to be masked from the log messages at runtime Relates-To: NLAM-140 Signed-off-by: Rustam Gamidov <[email protected]> * Extend Logs tests caused by formatting changes Codecov prefers to have patch config to be not lower than the rest of repository. The file has not been formatted properly before so there are changes not related to the censoring Relates-To: NLAM-140 Signed-off-by: Rustam Gamidov <[email protected]> * Add removing censor API to Log There are secrets that can be updated with time and it make sense not to censor them anymore not to let performance suffer. Relates-To: NLAM-140 Signed-off-by: Rustam Gamidov <[email protected]> --------- Signed-off-by: Rustam Gamidov <[email protected]>
1 parent 1d3c957 commit 766d495

File tree

3 files changed

+199
-21
lines changed

3 files changed

+199
-21
lines changed

olp-cpp-sdk-core/include/olp/core/logging/Log.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,26 @@ class CORE_API Log {
562562
const std::string& message, const char* file,
563563
unsigned int line, const char* function,
564564
const char* fullFunction);
565+
566+
/**
567+
* @brief Adds a line to be censored out from the log.
568+
*
569+
* Censoring out is a replacement with a predefiend mask with length not
570+
* correlated with the original line length.
571+
*
572+
* @param message The line to be censored out from the log.
573+
*/
574+
static void addCensor(const std::string& message);
575+
576+
/**
577+
* @brief Removes a line from censoring out from the log.
578+
*
579+
* Censoring out is a replacement with a predefiend mask with length not
580+
* correlated with the original line length.
581+
*
582+
* @param message The line to be excluded from censoring out from the log.
583+
*/
584+
static void removeCensor(const std::string& message);
565585
};
566586
} // namespace logging
567587
} // namespace olp

olp-cpp-sdk-core/src/logging/Log.cpp

Lines changed: 107 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,25 @@
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

3133
namespace olp {
3234
namespace 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+
3345
class 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

8099
LogImpl::LogImpl()
@@ -120,7 +139,8 @@ void LogImpl::setLevel(Level level, const std::string& tag) {
120139
}
121140

122141
porting::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

132152
void 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

138159
void LogImpl::clearLevels() { m_logLevels.clear(); }
139160

140161
bool 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

146168
bool 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

187244
bool 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

195253
Configuration 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

202261
void 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

208268
Level 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

215276
void 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

222284
void 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

232296
porting::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

239304
void 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

245311
void Log::clearLevels() {
246-
if (!LogImpl::aliveStatus()) return;
312+
if (!LogImpl::aliveStatus())
313+
return;
247314

248315
LogImpl::getInstance().locked([](LogImpl& log) { log.clearLevels(); });
249316
}
250317

251318
void 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

264333
bool 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

271341
bool 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

Comments
 (0)