Skip to content

Commit 45e3025

Browse files
committed
Initial Commit
0 parents  commit 45e3025

12 files changed

Lines changed: 427 additions & 0 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.vscode/
2+
build/

CMakeLists.txt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(AsyncLogger LANGUAGES CXX VERSION 0.0.1 DESCRIPTION "A lightweight C++20 asyncronous logger.")
4+
5+
set(SRC_DIR "${PROJECT_SOURCE_DIR}/src/")
6+
7+
# check std::format support
8+
if(NOT USE_FMT)
9+
include(CheckIncludeFileCXX)
10+
check_include_file_cxx("format" CXX_FORMAT_SUPPORT)
11+
else()
12+
set(CXX_FORMAT_SUPPORT 0)
13+
endif()
14+
15+
file(GLOB_RECURSE SRC_FILES
16+
"${SRC_DIR}**.cpp"
17+
"${SRC_DIR}**.hpp"
18+
)
19+
20+
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
21+
22+
if(CXX_FORMAT_SUPPORT)
23+
message("Using std::format for formatting, you can set USE_FMT to force fmt::format instead.")
24+
else()
25+
message("Using fmt::format for formatting.")
26+
include(FetchContent)
27+
28+
FetchContent_Declare(
29+
fmt
30+
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
31+
GIT_TAG 9.1.0
32+
GIT_PROGRESS TRUE
33+
)
34+
FetchContent_MakeAvailable(fmt)
35+
36+
target_link_libraries(${PROJECT_NAME} fmt)
37+
endif()
38+
39+
# does the -lpthread linking for us on Linux
40+
find_package(Threads REQUIRED)
41+
target_link_libraries(${PROJECT_NAME} Threads::Threads )
42+
43+
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER src/Logger.hpp)
44+
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
45+
46+
target_include_directories(${PROJECT_NAME} PUBLIC ${SRC_DIR})

src/LogCapture.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "LogCapture.hpp"
2+
#include "Logger.hpp"
3+
4+
namespace base
5+
{
6+
LogCapture::LogCapture(const eLogLevel level, std::source_location&& location) :
7+
m_Level(level),
8+
m_Location(location)
9+
{
10+
11+
}
12+
13+
LogCapture::~LogCapture()
14+
{
15+
m_Stream << '\n';
16+
Logger::PushMessage(m_Level, std::move(m_Location), std::move(m_Stream.str()));
17+
}
18+
}

src/LogCapture.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
#include <source_location>
3+
#include <sstream>
4+
#include "LogLevel.hpp"
5+
6+
namespace base
7+
{
8+
class Logger;
9+
class LogCapture
10+
{
11+
public:
12+
LogCapture(const eLogLevel level, std::source_location&& location);
13+
~LogCapture();
14+
15+
template<typename T>
16+
std::ostream& operator<< (const T& d);
17+
18+
private:
19+
const eLogLevel m_Level;
20+
std::source_location m_Location;
21+
std::ostringstream m_Stream;
22+
23+
};
24+
25+
template<typename T>
26+
std::ostream& LogCapture::operator<< (const T& d)
27+
{
28+
m_Stream << d;
29+
return m_Stream;
30+
}
31+
32+
}

src/LogIntermediate.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "LogIntermediate.hpp"
2+
3+
namespace base
4+
{
5+
LogIntermediate::LogIntermediate(const std::string_view formatString, const std::source_location location) :
6+
m_FormatString(formatString),
7+
m_Location(location)
8+
{
9+
10+
}
11+
12+
LogIntermediate::LogIntermediate(const char* formatString, const std::source_location location) :
13+
m_FormatString(formatString),
14+
m_Location(location)
15+
{
16+
17+
}
18+
19+
const std::string_view LogIntermediate::FormatString() const
20+
{
21+
return m_FormatString;
22+
}
23+
24+
std::source_location&& LogIntermediate::Location()
25+
{
26+
return std::move(m_Location);
27+
}
28+
}

src/LogIntermediate.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
#include <source_location>
3+
#include <string_view>
4+
5+
namespace base
6+
{
7+
class LogIntermediate
8+
{
9+
public:
10+
LogIntermediate(const std::string_view formatString, const std::source_location location = std::source_location::current());
11+
LogIntermediate(const char* formatString, const std::source_location location = std::source_location::current());
12+
virtual ~LogIntermediate() = default;
13+
14+
const std::string_view FormatString() const;
15+
std::source_location&& Location();
16+
17+
private:
18+
const std::string_view m_FormatString;
19+
std::source_location m_Location;
20+
21+
};
22+
}

src/LogLevel.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
namespace base
4+
{
5+
enum eLogLevel
6+
{
7+
DEBUG,
8+
INFO,
9+
WARNING,
10+
ERROR
11+
};
12+
}

src/LogMessage.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "LogMessage.hpp"
2+
#include "LogLevel.hpp"
3+
4+
namespace base
5+
{
6+
LogMessage::LogMessage(const eLogLevel level, std::source_location&& location, std::string&& message) :
7+
m_Level(level),
8+
m_Location(location),
9+
m_Message(message)
10+
{
11+
12+
}
13+
14+
const eLogLevel& LogMessage::Level() const
15+
{
16+
return m_Level;
17+
}
18+
19+
const std::source_location& LogMessage::Location() const
20+
{
21+
return m_Location;
22+
}
23+
24+
const std::string& LogMessage::Message() const
25+
{
26+
return m_Message;
27+
}
28+
29+
}

src/LogMessage.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
#include <source_location>
3+
#include <string>
4+
#include "LogLevel.hpp"
5+
6+
namespace base
7+
{
8+
class LogMessage
9+
{
10+
public:
11+
LogMessage(const eLogLevel level, std::source_location&& location, std::string&& message);
12+
virtual ~LogMessage() = default;
13+
14+
const eLogLevel& Level() const;
15+
const std::source_location& Location() const;
16+
const std::string& Message() const;
17+
18+
private:
19+
const eLogLevel m_Level;
20+
const std::source_location m_Location;
21+
const std::string m_Message;
22+
23+
};
24+
}

src/Logger.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "Logger.hpp"
2+
#include "LogCapture.hpp"
3+
#include "LogMessage.hpp"
4+
5+
namespace base
6+
{
7+
LogCapture LOG(const eLogLevel level, std::source_location location)
8+
{
9+
return LogCapture{ level, std::move(location) };
10+
}
11+
12+
void Logger::AddSink(LogSink sink)
13+
{
14+
Logger::GetInstance().m_Sinks.push_back(sink);
15+
}
16+
17+
void Logger::Destroy()
18+
{
19+
Logger::GetInstance().DestroyImpl();
20+
}
21+
22+
void Logger::Init()
23+
{
24+
Logger::GetInstance().InitImpl();
25+
}
26+
27+
void Logger::PushMessage(const eLogLevel level, std::source_location&& location, std::string&& message) noexcept
28+
{
29+
auto msgPtr = std::make_shared<LogMessage>(level, std::move(location), std::move(message));
30+
31+
Logger::GetInstance().QueueMessage(std::move(msgPtr));
32+
}
33+
34+
void Logger::CallSinks(LogMessagePtr msgPtr)
35+
{
36+
for (const auto &sink : m_Sinks)
37+
{
38+
sink(msgPtr);
39+
}
40+
}
41+
42+
void Logger::DestroyImpl()
43+
{
44+
m_Queue.push([this]
45+
{
46+
m_Running = false;
47+
});
48+
m_LogWorker.join();
49+
}
50+
51+
void Logger::InitImpl()
52+
{
53+
m_Running = true;
54+
m_LogWorker = std::thread([this]
55+
{
56+
while (m_Running)
57+
{
58+
std::function<void()> func;
59+
m_Queue.wait_and_pop(func);
60+
func();
61+
}
62+
});
63+
}
64+
65+
void Logger::QueueMessage(LogMessagePtr msgPtr)
66+
{
67+
m_Queue.push([this, msgPtr = std::move(msgPtr)]
68+
{
69+
CallSinks(msgPtr);
70+
});
71+
}
72+
}

0 commit comments

Comments
 (0)