BuildRequires: pkgconfig(libprocps)
BuildRequires: pkgconfig(libsystemd)
BuildRequires: pkgconfig(openssl)
-# policyd BRs
+# vist BRs
+BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(klay)
BuildRequires: pkgconfig(libtzplatform-config)
Requires: glog
systemd)
IF(DEFINED GBS_BUILD)
- SET(GBS_ONLY_PACKAGES klay
- vconf)
+ SET(GBS_ONLY_PACKAGES klay dlog)
PKG_CHECK_MODULES(GBS_DEPS REQUIRED ${GBS_ONLY_PACKAGES})
INCLUDE_DIRECTORIES(SYSTEM ${GBS_DEPS_INCLUDE_DIRS})
namespace tables {
QueryData genPolicy(QueryContext& context) try {
- INFO(VIST, "Select query about policy table.");
+ INFO(VIST) << "Select query about policy table.";
QueryData results;
if (context.constraints["name"].exists(EQUALS)) { /// where clause
return results;
} catch (...) {
- ERROR(VIST, "Failed to select query on policy.");
+ ERROR(VIST) << "Failed to select query on policy.";
Row r;
return { r };
}
QueryData updatePolicy(QueryContext& context, const PluginRequest& request) try {
- INFO(VIST, "Update query about policy table.");
+ INFO(VIST) << "Update query about policy table.";
if (request.count("json_value_array") == 0)
throw std::runtime_error("Wrong request format. Not found json value.");
r["status"] = "success";
return { r };
} catch (...) {
+ ERROR(VIST) << "Failed to update query on policy.";
Row r;
return { r };
}
namespace tables {
QueryData genPolicyAdmin(QueryContext& context) try {
- INFO(VIST, "Select query about policy-admin table.");
+ INFO(VIST) << "Select query about policy-admin table.";
QueryData results;
auto admins = vist::policy::API::Admin::GetAll();
Row r;
r["name"] = SQL_TEXT(admin);
- DEBUG(VIST, "Admin info [name]: " << r["name"]);
+ DEBUG(VIST) << "Admin info [name]: " << r["name"];
results.emplace_back(std::move(r));
}
return results;
} catch (...) {
- ERROR(VIST, "Failed to select query on policy-admin.");
+ ERROR(VIST) << "Failed to select query on policy-admin.";
Row r;
return { r };
}
QueryData insertPolicyAdmin(QueryContext& context, const PluginRequest& request) try {
- INFO(VIST, "Insert query about policy-admin table.");
+ INFO(VIST) << "Insert query about policy-admin table.";
if (request.count("json_value_array") == 0)
throw std::runtime_error("Wrong request format. Not found json value.");
auto admin = parseAdmin(request.at("json_value_array"));
- DEBUG(VIST, "Admin info [name]: " << admin);
+ DEBUG(VIST) << "Admin info [name]: " << admin;
vist::policy::API::Admin::Enroll(admin);
Row r;
r["status"] = "success";
return { r };
} catch (...) {
- ERROR(VIST, "Failed to insert query on policy-admin.");
+ ERROR(VIST) << "Failed to insert query on policy-admin.";
Row r;
return { r };
}
QueryData deletePolicyAdmin(QueryContext& context, const PluginRequest& request) try {
- INFO(VIST, "Delete query about policy-admin table.");
+ INFO(VIST) << "Delete query about policy-admin table.";
if (request.count("json_value_array") == 0)
throw std::runtime_error("Wrong request format. Not found json value.");
auto admin = parseAdmin(request.at("json_value_array"), false);
- DEBUG(VIST, "Admin info [name]: " << admin);
+ DEBUG(VIST) << "Admin info [name]: " << admin;
vist::policy::API::Admin::Disenroll(admin);
Row r;
r["status"] = "success";
return { r };
} catch (...) {
- ERROR(VIST, "Failed to delete query on policy-admin.");
+ ERROR(VIST) << "Failed to delete query on policy-admin.";
Row r;
return { r };
}
SET(${TARGET_VIST_LIB}_SRCS "")
SET(${TARGET_VIST_LIB}_TESTS "")
-SET(DEPENDENCY klay)
+SET(DEPENDENCY klay dlog)
PKG_CHECK_MODULES(VIST_DEPS REQUIRED ${DEPENDENCY})
ADD_SUBDIRECTORY(service)
ADD_LIBRARY(${TARGET_VIST_LIB} STATIC ${${TARGET_VIST_LIB}_SRCS})
-TARGET_LINK_LIBRARIES(${TARGET_VIST_LIB} ${VSIT_DEPS_LIBRARIES}
+TARGET_LINK_LIBRARIES(${TARGET_VIST_LIB} ${VIST_DEPS_LIBRARIES}
${TARGET_VIST_POLICY_LIB}
${TARGET_OSQUERY_LIB})
Rows Query::Execute(const std::string& statement)
{
- INFO(VIST_CLIENT, "Query execution: " << statement);
+ INFO(VIST_CLIENT) << "Query execution: " << statement;
auto& client = ipc::Client::Instance(SOCK_ADDR);
return client->methodCall<Rows>("Vist::query", statement);
result.seconds = time.at(&Time::seconds);
/// Once query execution
- INFO(VIST_CLIENT, "[Test] time table:");
- INFO(VIST_CLIENT, "\t hour: " << result.hour);
- INFO(VIST_CLIENT, "\t minutes: " << result.minutes);
- INFO(VIST_CLIENT, "\t seconds: " << result.seconds);
+ INFO(VIST_CLIENT) << "[Test] time table:";
+ INFO(VIST_CLIENT) << "\t hour: " << result.hour;
+ INFO(VIST_CLIENT) << "\t minutes: " << result.minutes;
+ INFO(VIST_CLIENT) << "\t seconds: " << result.seconds;
/// Each query execution
- INFO(VIST_CLIENT, "[Test] time table:");
- INFO(VIST_CLIENT, "\t hour: " << VirtualRow<Time>().at(&Time::hour));
- INFO(VIST_CLIENT, "\t minutes: " << VirtualRow<Time>().at(&Time::minutes));
- INFO(VIST_CLIENT, "\t seconds: " << VirtualRow<Time>().at(&Time::seconds));
+ INFO(VIST_CLIENT) << "[Test] time table:";
+ INFO(VIST_CLIENT) << "\t hour: " << VirtualRow<Time>().at(&Time::hour);
+ INFO(VIST_CLIENT) << "\t minutes: " << VirtualRow<Time>().at(&Time::minutes);
+ INFO(VIST_CLIENT) << "\t seconds: " << VirtualRow<Time>().at(&Time::seconds);
EXPECT_NE(result.hour, -1);
EXPECT_NE(result.minutes, -1);
result.seconds = time[&Time::seconds];
/// Once query execution
- INFO(VIST_CLIENT, "[Test] time table:");
- INFO(VIST_CLIENT, "\t hour: " << result.hour);
- INFO(VIST_CLIENT, "\t minutes: " << result.minutes);
- INFO(VIST_CLIENT, "\t seconds: " << result.seconds);
+ INFO(VIST_CLIENT) << "[Test] time table:";
+ INFO(VIST_CLIENT) << "\t hour: " << result.hour;
+ INFO(VIST_CLIENT) << "\t minutes: " << result.minutes;
+ INFO(VIST_CLIENT) << "\t seconds: " << result.seconds;
EXPECT_NE(result.hour, -1);
EXPECT_NE(result.minutes, -1);
result.on_disk = p.at(&Processes::on_disk);
result.parent = p.at(&Processes::parent);
- INFO(VIST_CLIENT, "[Test] Processes table:");
- INFO(VIST_CLIENT, "\t pid: " << result.pid);
- INFO(VIST_CLIENT, "\t name: " << result.name);
- INFO(VIST_CLIENT, "\t path: " << result.path);
- INFO(VIST_CLIENT, "\t cmdline: " << result.cmdline);
- INFO(VIST_CLIENT, "\t uid: " << result.uid);
- INFO(VIST_CLIENT, "\t gid: " << result.gid);
- INFO(VIST_CLIENT, "\t euid: " << result.euid);
- INFO(VIST_CLIENT, "\t egid: " << result.egid);
- INFO(VIST_CLIENT, "\t on_disk: " << result.on_disk);
- INFO(VIST_CLIENT, "\t parent: " << result.parent);
+ INFO(VIST_CLIENT) << "[Test] Processes table:";
+ INFO(VIST_CLIENT) << "\t pid: " << result.pid;
+ INFO(VIST_CLIENT) << "\t name: " << result.name;
+ INFO(VIST_CLIENT) << "\t path: " << result.path;
+ INFO(VIST_CLIENT) << "\t cmdline: " << result.cmdline;
+ INFO(VIST_CLIENT) << "\t uid: " << result.uid;
+ INFO(VIST_CLIENT) << "\t gid: " << result.gid;
+ INFO(VIST_CLIENT) << "\t euid: " << result.euid;
+ INFO(VIST_CLIENT) << "\t egid: " << result.egid;
+ INFO(VIST_CLIENT) << "\t on_disk: " << result.on_disk;
+ INFO(VIST_CLIENT) << "\t parent: " << result.parent;
}
}
for(const auto& row : table) {
Policy policy = { row[&Policy::name], row[&Policy::value] };
- INFO(VIST_CLIENT, "[Test] Policy table:");
- INFO(VIST_CLIENT, "\t name: " << policy.name);
- INFO(VIST_CLIENT, "\t value: " << policy.value);
+ INFO(VIST_CLIENT) << "[Test] Policy table:";
+ INFO(VIST_CLIENT) << "\t name: " << policy.name;
+ INFO(VIST_CLIENT) << "\t value: " << policy.value;
}
}
std::string value = this->data.at(key);
if (value.empty()) {
- ERROR(VIST, "The value of key[" << key << "] is not exist.");
+ ERROR(VIST) << "The value of key[" << key << "] is not exist.";
return Member();
}
try {
return boost::lexical_cast<Member>(value);
} catch (...) {
- ERROR(VIST, "Failed to casting [key]: " << key);
+ ERROR(VIST) << "Failed to casting [key]: " << key;
return Member();
}
}
* limitations under the License
*/
/*
+ * @brief Enum based exception handling
* @usage
+ * boilerplate : THROW(${ERROR_CODE: ENUM_TYPE}) << ${MESSAGE_STREAM}
+ *
* enum class ErrCode {
* LogicError = 1,
* RuntimeError
{
std::stringstream ss;
ss << "[" << file << ":" << line << " " << function << "()]"
- << "[" << boost::core::demangle(typeid(ec).name())
- << "(" << static_cast<typename std::underlying_type_t<ErrCode>>(ec) << ")]";
+ << "[" << boost::core::demangle(typeid(ec).name()) << "("
+ << static_cast<typename std::underlying_type_t<ErrCode>>(ec) << ")] ";
message = ss.str();
}
template<typename T>
Self& operator<<(const T& arg) noexcept
{
- message += (static_cast<std::stringstream&>(std::stringstream() << arg)).str();
+ std::stringstream ss;
+ ss << arg;
+ message += ss.str();
return *this;
}
* See the License for the specific language governing permissions and
* limitations under the License
*/
+/*
+ * @brief Logging macro for dlog
+ * @usage
+ * boilerplate : ${LEVEL}(${TAG}) << ${MESSAGE_STREAM}
+ *
+ * INFO(VIST) << "Info message" << 1;
+ * DEBUG(VIST) << "Debug message" << 2 << 'a';
+ * WARN(VIST) << "Warning message" << 3 << 'b' << true;
+ * ERROR(VIST) << "Error message" << 4 << 'c' << false << 0.0f;
+ */
#pragma once
-#include <klay/audit/dlog-sink.h>
-#include <klay/audit/logger.h>
-
+#include <cstring>
#include <memory>
+#include <sstream>
+#include <string>
-#define VIST vist::Logger::Instance()
-#define VIST_CLIENT vist::Logger::ClientInstance()
+#include <dlog.h>
namespace vist {
-class Logger final {
-public:
- Logger(const Logger&) = delete;
- Logger& operator=(const Logger&) = delete;
+enum class LogLevel {
+ Info,
+ Debug,
+ Warn,
+ Error
+};
- Logger(Logger&&) = default;
- Logger& operator=(Logger&&) = default;
+struct LogRecord {
+ LogLevel level = LogLevel::Debug;
+ std::string tag;
+ std::string file;
+ unsigned int line = 0;
+ std::string func;
+ std::string message;
+};
- static klay::LogSink* Instance()
+class LogStream final {
+public :
+ LogStream(LogRecord record) noexcept : record(std::move(record)) {}
+ ~LogStream() noexcept
{
- static Logger instance("VIST");
- return &instance.logSink;
+ std::stringstream format;
+ format << "[" << record.file << ":" << record.line
+ << " " << record.func << "()] ";
+
+ record.message += (format.str() + stream.str());
+ log();
}
- static klay::LogSink* ClientInstance()
+ LogStream(const LogStream&) = delete;
+ LogStream& operator=(const LogStream&) = delete;
+
+ LogStream(LogStream&&) = default;
+ LogStream& operator=(LogStream&&) = default;
+
+ template<typename T>
+ LogStream& operator<<(const T& arg)
{
- static Logger instance("VIST_CLIENT");
- return &instance.logSink;
+ stream << arg;
+ return *this;
}
private:
- explicit Logger(const std::string& tag) : logSink(tag) {}
- ~Logger() = default;
+ inline void log() const noexcept
+ {
+ switch (record.level) {
+ case LogLevel::Info:
+ SLOG(LOG_INFO, record.tag.c_str(), "%s", record.message.c_str());
+ return;
+ case LogLevel::Debug:
+ SLOG(LOG_DEBUG, record.tag.c_str(), "%s", record.message.c_str());
+ return;
+ case LogLevel::Warn:
+ SLOG(LOG_WARN, record.tag.c_str(), "%s", record.message.c_str());
+ return;
+ case LogLevel::Error:
+ SLOG(LOG_ERROR, record.tag.c_str(), "%s", record.message.c_str());
+ return;
+ }
+ }
- klay::DlogLogSink logSink;
+ LogRecord record;
+ std::ostringstream stream;
};
+#ifndef __FILENAME__
+#define __FILENAME__ \
+(::strrchr(__FILE__, '/') ? ::strrchr(__FILE__, '/') + 1 : __FILE__)
+#endif
+
+#define LOG(level, tag) vist::LogStream(LOGCAT(vist::LogLevel::level, #tag))
+#define LOGCAT(level, tag) \
+ vist::LogRecord {level, tag, __FILENAME__, __LINE__, __func__}
+
+#define NULLSTREAM std::ostringstream()
+
+#define INFO(tag) LOG(Info, tag)
+#define ERROR(tag) LOG(Error, tag)
+
+#if !defined(NDEBUG)
+#define DEBUG(tag) LOG(Debug, tag)
+#define WARN(tag) LOG(Warn, tag)
+#else
+#define DEBUG(tag) NULLSTREAM
+#define WARN(tag) NULLSTREAM
+#endif /// NDEBUG
+
} // namespace vist
SET(${TARGET_VIST_POLICY_LIB}_SRCS "")
+PKG_CHECK_MODULES(VIST_POLICY_DEPS REQUIRED klay dlog)
+
+INCLUDE_DIRECTORIES(SYSTEM . common ${VIST_POLICY_DEPS_INCLUDE_DIRS})
+
ADD_VIST_POLICY_LIBRARY(vist_policy_core core/api.cpp
core/policy-manager.cpp
core/policy-loader.cpp
ADD_VIST_TEST(${POLICY_SDK_TESTS})
ADD_LIBRARY(${TARGET_VIST_POLICY_LIB} STATIC ${${TARGET_VIST_POLICY_LIB}_SRCS})
-TARGET_LINK_LIBRARIES(${TARGET_VIST_POLICY_LIB} pthread dl)
+TARGET_LINK_LIBRARIES(${TARGET_VIST_POLICY_LIB} ${VIST_POLICY_DEPS_LIBRARIES}
+ pthread
+ dl)
{
loadProviders(PLUGIN_INSTALL_DIR);
int cnt = loadPolicies();
- INFO(VIST, std::to_string(cnt) + "-policies loaded");
+ INFO(VIST) << std::to_string(cnt) << "-policies loaded";
}
std::pair<int, int> PolicyManager::loadProviders(const std::string& path)
{
- INFO(VIST, "Load policies from :" << path);
+ INFO(VIST) << "Load policies from :" << path;
klay::File dir(path);
if (!dir.exists() || !dir.isDirectory())
throw std::invalid_argument("Plugin directory is wrong.: " + path);
try {
auto provider = PolicyLoader::load(iter->getPath());
- DEBUG(VIST, "Loaded provider: " << provider->getName());
+ DEBUG(VIST) << "Loaded provider: " << provider->getName();
bool exist = false;
for (const auto& p : this->providers) {
this->providers.emplace_back(std::move(provider));
} catch (const std::exception& e) {
++failed;
- ERROR(VIST, "Failed to load: " << iter->getPath() << e.what());
+ ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what();
continue;
}
++passed;
}
- INFO(VIST, "Loaded result >> passed: " << passed << ", failed: " << failed);
+ INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed;
return std::make_pair(passed, failed);
}
/// Check the policy is defined on policy-storage
if (!storage.exists(pair.first)) {
- INFO(VIST, "Define policy: " << pair.first);
+ INFO(VIST) << "Define policy: " << pair.first;
storage.define(pair.first, pair.second->getInitial().value);
changed = true;
}
void PolicyStorage::sync()
{
- DEBUG(VIST, "Sync policy storage to cache object.");
+ DEBUG(VIST) << "Sync policy storage to cache object.";
syncAdmin();
syncPolicyActivated();
syncPolicyDefinition();
PolicyDefinition pd;
pd.name = std::string(stmt.getColumn(0));
pd.ivalue = stmt.getColumn(1);
- DEBUG(VIST, "Defined policy:" + pd.name);
+ DEBUG(VIST) << "Defined policy:" << pd.name;
this->definitions.emplace(pd.name, std::move(pd));
}
- DEBUG(VIST, definitions.size() << "- policies synced.");
+ DEBUG(VIST) << definitions.size() << "- policies synced.";
}
void PolicyStorage::syncAdmin()
while (stmt.step())
this->admins.emplace_back(std::string(stmt.getColumn(0)));
- DEBUG(VIST, admins.size() << "-admins synced.");
+ DEBUG(VIST) << admins.size() << "-admins synced.";
}
void PolicyStorage::syncPolicyActivated()
this->activatedPolicies.emplace(pa.policy, std::move(pa));
}
- DEBUG(VIST, activatedPolicies.size() << "- activated-policies synced.");
+ DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced.";
}
std::string PolicyStorage::getScript(const std::string& name)
void PolicyStorage::define(const std::string& policy, int ivalue)
{
if (definitions.find(policy) != definitions.end()) {
- INFO(VIST, "Policy is already defined: " + policy);
+ INFO(VIST) << "Policy is already defined: " << policy;
return;
}
void PolicyStorage::enroll(const std::string& name)
{
- INFO(VIST, "Enroll admin: " + name);
+ INFO(VIST) << "Enroll admin: " << name;
if (std::find(admins.begin(), admins.end(), name) != admins.end()) {
- ERROR(VIST, "Admin is aleady enrolled.: " + name);
+ ERROR(VIST) << "Admin is aleady enrolled.: " << name;
return;
}
std::string query = adminTable.insert(&Admin::name);
- DEBUG(VIST, "Enroll admin query statement: " + query);
+ DEBUG(VIST) << "Enroll admin query statement: " << query;
database::Statement stmt(*database, query);
stmt.bind(1, name);
if (!stmt.exec())
syncPolicyActivated();
int count = activatedPolicies.size() / admins.size();
- INFO(VIST, "Admin[" + name + "] manages " + std::to_string(count) + "-policies.");
+ INFO(VIST) << "Admin[" << name << "] manages "
+ << std::to_string(count) << "-policies.";
}
void PolicyStorage::disenroll(const std::string& name)
{
- INFO(VIST, "Disenroll admin: " + name);
+ INFO(VIST) << "Disenroll admin: " << name;
auto iter = std::find(admins.begin(), admins.end(), name);
if (iter == admins.end()) {
- ERROR(VIST, "Not exist admin: " + name);
+ ERROR(VIST) << "Not exist admin: " << name;
return;
} else {
admins.erase(iter);
const std::string& policy,
const PolicyValue& value)
{
- DEBUG(VIST, "Policy-update is called by admin: " + admin + ", about: " + policy +
- ", value: " + std::to_string(value));
+ DEBUG(VIST) << "Policy-update is called by admin: " << admin
+ << ", about: " << policy << ", value: " << std::to_string(value);
if (std::find(admins.begin(), admins.end(), admin) == admins.end())
throw std::runtime_error("Not exist admin: " + admin);
else
strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value;
- DEBUG(VIST, "The strictest of policy[" + policy +
- "] : " + std::to_string(strictestPtr->value));
+ DEBUG(VIST) << "The strictest of policy[" << policy
+ << "] : " + std::to_string(strictestPtr->value);
}
if (strictestPtr == nullptr)
void Vist::start()
{
- INFO(VIST, "Vist daemon starts.");
+ INFO(VIST) << "Vist daemon starts.";
auto& server = ipc::Server::Instance(SOCK_ADDR);
server->expose(this, "", (QUERY_RET_TYPE)(Vist::query)(std::string));
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+#include <gtest/gtest.h>
+
+#include <vist/logger.hpp>
+
+class LoggerTests : public testing::Test {};
+
+TEST_F(LoggerTests, logging)
+{
+ INFO(VIST) << "Info message" << 1;
+ DEBUG(VIST) << "Debug message" << 2 << 'a';
+ WARN(VIST) << "Warn message" << 3 << 'b' << true;
+ ERROR(VIST) << "Error message" << 4 << 'c' << false << 0.0f;
+}