Hubris Engine Dev
A Project to learn and get into Game Engine developement.
 
Loading...
Searching...
No Matches
Logger.h
Go to the documentation of this file.
1#pragma once
2#ifdef HBR_LOGGER
3#else
4#define HBR_LOGGER
5#define LOG_FILE_LIMIT 5
6#define LOG_FILE_MAX_SIZE 5 * 1024 * 1024 //5 MB is the default log file size limit.
7#include <iostream>
8#include <utility>
9#include <chrono>
10#include <thread>
11#include <iomanip>
12#include <sstream>
13#include <unordered_map>
14#include "fmt/core.h"
15#include <fmt/std.h>
16
17namespace Hubris {
18 class Logger {
19 private:
20 static inline std::unordered_map<std::string, FILE*> LogFiles;
21 static inline FILE* LogFile = nullptr;
22
23 static std::string getCurrentTime() {
24 auto now = std::chrono::system_clock::now();
25 auto in_time_t = std::chrono::system_clock::to_time_t(now);
26 //
27 return fmt::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(in_time_t));;
28 }
29
30 static FILE* OpenAndReturn(std::string fileName){
31 FILE* f;
32 errno_t err = fopen_s(&f, fileName.c_str(), "a+");
33 if(err != 0){
34 std::cerr << "Logger: Error opening file " << fileName << std::endl;
35 }
36 LogFiles[fileName] = f;
37 return f;
38 }
39
40 public:
45 static void Start(){
46 // int logIndex = 0;
47 // while(logIndex < LOG_FILE_LIMIT){
48 // if(std::filesystem::file_size(fmt::format("Engine{}.log", logIndex ? std::to_string(logIndex) : "")) > LOG_FILE_MAX_SIZE){
49 // ++logIndex;
50 // continue;
51 // }
52 // break;
53 // }
54 // //TODO: have a way to replace old Files.
55 errno_t err = fopen_s(&LogFile, "Engine.log", "a+");
56 if(err != 0){
57 std::cout << "Fatal: Failed to open log file\n";
58 }
59 }
60
64 static void Close(){
65 fflush(LogFile);
66 fclose(LogFile);
67 for(const auto& file : LogFiles){
68 fflush(file.second);
69 fclose(file.second);
70 }
71 }
72
76 static void Flush(){
77 std::cout.flush();
78 fflush(LogFile);
79 for(const auto& file : LogFiles){
80 fflush(file.second);
81 }
82 }
83
86 template<typename ...Args>
87 static void FileLog(std::string fileName, const char* message, Args&& ...args){
88 FILE* file = LogFiles[fileName];
89 file = (file ? file : OpenAndReturn(fileName));
90 std::cout << fmt::format(message, std::forward<Args>(args)...) << std::endl;
91 fmt::println(file, "({})[ThreadID: {}] Fatal: {}", getCurrentTime(), std::this_thread::get_id(), fmt::format(message, std::forward<Args>(args)...));
92 }
93
94 //template<typename ...Args>
95 //static void Log(fmt::string_view message, Args&&... args) {
96 // const auto formatted = fmt::format(message, std::forward<Args>(args)...);
97 // std::cout << formatted << std::endl;
98 // if (!LogFile) return;
99 // fmt::println(LogFile, "({})[ThreadID: {}] Info: {}", getCurrentTime(), std::this_thread::get_id(), formatted);
100 // fflush(LogFile);
101 //}
102
103
104 static void Log(const char* message) {
105 const auto formatted = fmt::format("({})[ThreadID: {}] Info: {}", getCurrentTime(), std::this_thread::get_id(), message);
106 std::cout << formatted << std::endl;
107 if (!LogFile) return;
108 fmt::println(LogFile, "{}", formatted);
109 fflush(LogFile);
110 }
111
112 static void Log(const std::string& message) {
113 const auto formatted = fmt::format("({})[ThreadID: {}] Info: {}", getCurrentTime(), std::this_thread::get_id(), message.c_str());
114 std::cout << formatted << std::endl;
115 if (!LogFile) return;
116 fmt::println(LogFile, "{}", formatted);
117 fflush(LogFile);
118 }
119
120 template<typename ...Args>
121 static void Log(fmt::format_string<Args...> message, Args&&... args) {
122 //I wonder if this can be done in one operation ? Recursive formatting ?
123 const auto formatted = fmt::format(message, std::forward<Args>(args)...);
124 Log(formatted);
125 }
126
127 static void DbgLog(const std::string& message){
128 Log(message);
129 __debugbreak();
130 }
131
132 template<typename ...Args>
133 static void DbgLog(fmt::format_string<Args...> message, Args&&... args){
134 Log(message, std::forward(args)...);
135 __debugbreak();
136 }
137 /*template<typename ...Args>
138 static void Fatal(fmt::string_view message, Args&&... args) {
139 const auto formatted = fmt::format(message, std::forward<Args>(args)...);
140 std::cerr << fmt::format("({})[ThreadID: {}] Fatal: {}\n", getCurrentTime(), std::this_thread::get_id(), formatted);
141 if (!LogFile) return;
142 fmt::println(LogFile, "({})[ThreadID: {}] Fatal: {}", getCurrentTime(), std::this_thread::get_id(), formatted);
143 fflush(LogFile);
144 }*/
145
146 template<typename ...Args>
147 static void Fatal(fmt::format_string<Args...> message, Args&&... args) {
148 const auto formatted = fmt::format(message, std::forward<Args>(args)...);
149 std::cerr << fmt::format("({})[ThreadID: {}] Fatal: {}\n", getCurrentTime(), std::this_thread::get_id(), formatted);
150 if (!LogFile) return;
151 fmt::println(LogFile, "({})[ThreadID: {}] Fatal: {}", getCurrentTime(), std::this_thread::get_id(), formatted);
152 fflush(LogFile);
153 }
154
155 };
156}
157
158#endif
static void Log(const std::string &message)
Definition Logger.h:112
static void DbgLog(const std::string &message)
Definition Logger.h:127
static void Log(const char *message)
Definition Logger.h:104
static void DbgLog(fmt::format_string< Args... > message, Args &&... args)
Definition Logger.h:133
static void Start()
Starts the logger.
Definition Logger.h:45
static void Fatal(fmt::format_string< Args... > message, Args &&... args)
Definition Logger.h:147
static void Log(fmt::format_string< Args... > message, Args &&... args)
Definition Logger.h:121
static void Flush()
Flushes and keeps the files open.
Definition Logger.h:76
static void FileLog(std::string fileName, const char *message, Args &&...args)
Logs in a file, if the file is used for the first time, it is opened and kept in cache.
Definition Logger.h:87
static void Close()
Flushes and closes all the files used for logging.
Definition Logger.h:64
The Hubris Engine main namespace.
Definition EventBus.h:4