Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example and CustomLogger #1

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "external/spdlog"]
path = external/spdlog
url = https://github.com/gabime/spdlog.git
44 changes: 44 additions & 0 deletions example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "logfmt.h"

#define toFile false

// Compile with "g++ example.cpp logfmt.cpp -o example -Wall -Wextra -pedantic -std=c++17 -pthread -Iexternal/spdlog/include -fmax-errors=1 -O3 -march=native"
// dont forget to create logs folder if logging to file

int main()
{
std::string a ="testing";
float float_test = 2.8;
long long_test = 100;
logfmt log("test", toFile);

spdlog::set_level(spdlog::level::trace);
log.WithField(log.custom_field={{"animal", "walrus"}, {"total", 100}}).info("INFO of WALRUS and its total");
log.info("No Walrus");
log.WithField(log.custom_field={{"animal", "dog"}, {"total", float_test}}).warn("WARN of DOG and its total");
log.warn("No Dog");


log.OutputJSON(); //output in JSON format
log.WithField(log.custom_field={{"animal", "cat"}, {"total", long_test}}).critical("CRITICAL of CAT and its total");
log.critical("No Cat");
log.WithField(log.custom_field={{"animal", "falcon"}, {"total", 10}}).error("ERROR of FALCON and its total");
log.error("No Falcon");

auto staticformat = log.WithField(log.custom_field={{"float",float_test}, {"long", long_test}, {"string", a}});
staticformat.info("This is INFO with custom key");
staticformat.debug("This is DEBUG with custom key");
staticformat.trace("This is TRACE with custom key");
staticformat.warn("This is WARN with custom key");
staticformat.critical("This is CRITICAL with custom key");
staticformat.error("This is ERROR with custom key");

log.OutputDefault();
auto staticformat2 = log.WithField(log.custom_field={{"animal","griffin"}, {"rider", "azure"}, {"weapon", "spear"}});
staticformat2.info("This is INFO with custom key");
staticformat2.debug("This is DEBUG with custom key");
staticformat2.trace("This is TRACE with custom key");
staticformat2.warn("This is WARN with custom key");
staticformat2.critical("This is CRITICAL with custom key");
staticformat2.error("This is ERROR with custom key");
}
1 change: 1 addition & 0 deletions external/spdlog
Submodule spdlog added at 8179b2
285 changes: 285 additions & 0 deletions logfmt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
#include "logfmt.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////

//class Entry

//private
std::string logfmt::Entry::AddQuotation(std::string msg) //return quotation in message input
{
return "\"" + msg + "\"";
}

void logfmt::Entry::processKey(std::string& msg)
{
std::string pattern =" ";

for (auto& [key,val] : entry_field)
{
pattern = pattern + casting(key, val);
}

if(JSON)
{
msg = AddQuotation(msg);
}

msg = msg + pattern;
}

std::string logfmt::Entry::casting(std::string key, std::any val) //casting the value in map into string
{
std::string custom_string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refactor this function to multiple smaller function. Also, maybe it's better to use switch instead of if?

Maybe this would work:

std::string logfmt::Entry::casting(std::string key, std::any val) {
    std::string custom_string;

    if (JSON) {
        custom_string = cast_json(key, value);
    } else {
        custom_string = cast_key_value(key, value);
    }

    return custom_string;
}

std::string logfmt::Entry::cast_json(std::string key, std::any val) {
    switch (val.type()) {
        case typeid(char):
           ...
    }
}

if(JSON)
{
custom_string = custom_string + ", " + AddQuotation(key) + " : " ;
//check type for any_cast
if (val.type() == typeid(char)) //char
{
custom_string = custom_string + "\"";
custom_string += (std::any_cast<char>(val));
custom_string = custom_string + "\" ";
}
else if (val.type() == typeid(const char *)) //array of char
{
std::string temp(std::any_cast<const char *>(val));
custom_string = custom_string + AddQuotation(temp) + " ";
}
else if (val.type() == typeid(int)) //integer
{
custom_string = custom_string + std::to_string(std::any_cast<int>(val)) + " ";
}
else if (val.type() == typeid(float)) //float
{
custom_string = custom_string + std::to_string(std::any_cast<float>(val)) + " ";
}
else if (val.type() == typeid(double)) //double
{
custom_string = custom_string + std::to_string(std::any_cast<double>(val)) + " ";
}
else if (val.type() == typeid(bool)) //boolean
{
if (std::any_cast<bool>(val) == 1)
{
custom_string = custom_string + "true ";
}
else if (std::any_cast<bool>(val) == 0)
{
custom_string = custom_string + "false ";
}
}
else if (val.type() == typeid(std::string)) //string
{
custom_string = custom_string + AddQuotation(std::any_cast<std::string>(val)) + " ";
}
else if (val.type() == typeid(long)) //long
{
custom_string = custom_string + std::to_string(std::any_cast<long>(val)) + " ";
}
}
else
{
custom_string = custom_string + key + " = " ;
if (val.type() == typeid(char))
{
custom_string = custom_string + "\"";
custom_string += (std::any_cast<char>(val));
custom_string = custom_string + "\" ";
}
else if (val.type() == typeid(const char *))
{
std::string temp(std::any_cast<const char *>(val));
custom_string = custom_string + AddQuotation(temp) + " ";
}
else if (val.type() == typeid(int))
{
custom_string = custom_string + std::to_string(std::any_cast<int>(val)) + " ";
}
else if (val.type() == typeid(float))
{
custom_string = custom_string + std::to_string(std::any_cast<float>(val)) + " ";
}
else if (val.type() == typeid(double))
{
custom_string = custom_string + std::to_string(std::any_cast<double>(val)) + " ";
}
else if (val.type() == typeid(bool))
{
if (std::any_cast<bool>(val) == 1)
{
custom_string = custom_string + "true ";
}
else if (std::any_cast<bool>(val) == 0)
{
custom_string = custom_string + "false ";
}
}
else if (val.type() == typeid(std::string))
{
custom_string = custom_string + AddQuotation(std::any_cast<std::string>(val)) + " ";
}
else if (val.type() == typeid(long))
{
custom_string = custom_string + std::to_string(std::any_cast<long>(val)) + " ";
}
}

return custom_string;
}

//public
logfmt::Entry::Entry()
{
//default ctor (not used)
}

logfmt::Entry::Entry(std::shared_ptr<spdlog::logger>& log, bool JSON ) //ctor
{
entry_log = log;
this -> JSON = JSON;
}

logfmt::Entry& logfmt::Entry::WithField(std::map<std::string, std::any>& keyMap)
{
entry_field = keyMap;
return *this;
}
void logfmt::Entry::info(std::string msg)
{
processKey(msg);
entry_log -> info(msg);
}

void logfmt::Entry::trace(std::string msg)
{
processKey(msg);
entry_log -> trace(msg);
}

void logfmt::Entry::debug(std::string msg)
{
processKey(msg);
entry_log -> debug(msg);
}

void logfmt::Entry::warn(std::string msg)
{
processKey(msg);
entry_log -> warn(msg);
}

void logfmt::Entry::error(std::string msg)
{
processKey(msg);
entry_log -> error(msg);
}

void logfmt::Entry::critical(std::string msg)
{
processKey(msg);
entry_log -> critical(msg);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////
// logfmt implementation

logfmt::logfmt(std::string name, bool to_file) //constructor
{
if (to_file)
{
logger = spdlog::basic_logger_mt(name , "logs/basic-log.txt");
}
else
{
logger = spdlog::stdout_color_mt(name);
}
WriteFile = to_file;
JSONstatus = false;
}

// function
void logfmt::OutputJSON()
{
JSONstatus = true;
logger -> set_pattern(JSONformatter());
}

void logfmt::OutputDefault()
{
JSONstatus = false;
logger -> set_pattern("%+");
}

logfmt::Entry& logfmt::WithField(std::map<std::string, std::any>& keyMap)
{
loggerEntry = Entry(logger, JSONstatus);
return loggerEntry.WithField(keyMap);
}

std::string logfmt::AddQuotation(std::string msg) //return quotation in message input
{
return "\"" + msg + "\" ";
}

std::string logfmt::JSONformatter()
{
return "{ \"date\" : \"%d-%m-%Y\" , \"time\" : \"%H:%M:%S\" , \"name\" : \"%n\" , \"level\" : \"%^%l%$\" , \"message\" : %v}";
}

//basic logging
void logfmt::info(std::string msg)
{
if (JSONstatus)
{
msg = AddQuotation(msg);
}

logger -> info(msg);
}

void logfmt::trace(std::string msg)
{
if (JSONstatus)
{
msg = AddQuotation(msg);
}

logger -> trace(msg);
}
void logfmt::debug(std::string msg)
{
if (JSONstatus)
{
msg = AddQuotation(msg);
}

logger -> debug(msg);
}
void logfmt::warn(std::string msg)
{
if (JSONstatus)
{
msg = AddQuotation(msg);
}

logger -> warn(msg);
}
void logfmt::error(std::string msg)
{
if (JSONstatus)
{
msg = AddQuotation(msg);
}

logger -> error(msg);
}
void logfmt::critical(std::string msg)
{
if (JSONstatus)
{
msg = AddQuotation(msg);
}

logger -> critical(msg);
}
60 changes: 60 additions & 0 deletions logfmt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

#include <iostream>
#include <map>
#include <any>
#include <typeinfo>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"

class logfmt
{
private:
//member
class Entry
{
private:
//member
std::map<std::string, std::any> entry_field;
std::shared_ptr<spdlog::logger> entry_log;
bool JSON;
//function
std::string AddQuotation(std::string msg);
void processKey(std::string& msg);
std::string casting(std::string key, std::any val);
public:
Entry(); //default ctor
Entry(std::shared_ptr<spdlog::logger>& log, bool JSON ); //ctor with parameter
Entry& WithField(std::map<std::string, std::any>& keyMap);
void info(std::string msg);
void trace(std::string msg);
void debug(std::string msg);
void warn(std::string msg);
void error(std::string msg);
void critical(std::string msg);
};
Entry loggerEntry;
std::shared_ptr<spdlog::logger> logger;
bool JSONstatus; // make this true to make log in JSON form / false in normal form
bool WriteFile; // make this true to write log into file
public:
//member
std::map<std::string, std::any> custom_field;
//ctor
logfmt(std::string name, bool to_file);
//function
void OutputJSON();
void OutputDefault();
logfmt::Entry& WithField(std::map<std::string, std::any>& keyMap);
std::string JSONformatter();
std::string AddQuotation(std::string msg);

//basic logging
void info(std::string msg);
void trace(std::string msg);
void debug(std::string msg);
void warn(std::string msg);
void error(std::string msg);
void critical(std::string msg);
};
Loading