diff options
| author | 2018-07-03 00:26:45 -0400 | |
|---|---|---|
| committer | 2018-07-03 00:26:45 -0400 | |
| commit | 15e68cdbaac38bbf13cd4eb0d70d1e34b2fd4256 (patch) | |
| tree | 9d072a572c0037a44e1e35aeffc242d3772a383c /src/common | |
| parent | Merge pull request #612 from bunnei/fix-cull (diff) | |
| parent | Fix build and address review feedback (diff) | |
| download | yuzu-15e68cdbaac38bbf13cd4eb0d70d1e34b2fd4256.tar.gz yuzu-15e68cdbaac38bbf13cd4eb0d70d1e34b2fd4256.tar.xz yuzu-15e68cdbaac38bbf13cd4eb0d70d1e34b2fd4256.zip | |
Merge pull request #607 from jroweboy/logging
Logging - Customizable backends
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/assert.h | 5 | ||||
| -rw-r--r-- | src/common/common_paths.h | 3 | ||||
| -rw-r--r-- | src/common/file_util.cpp | 111 | ||||
| -rw-r--r-- | src/common/file_util.h | 11 | ||||
| -rw-r--r-- | src/common/logging/backend.cpp | 157 | ||||
| -rw-r--r-- | src/common/logging/backend.h | 87 | ||||
| -rw-r--r-- | src/common/logging/filter.cpp | 8 | ||||
| -rw-r--r-- | src/common/logging/log.h | 14 | ||||
| -rw-r--r-- | src/common/memory_util.cpp | 16 | ||||
| -rw-r--r-- | src/common/param_package.cpp | 12 | ||||
| -rw-r--r-- | src/common/string_util.cpp | 8 |
11 files changed, 334 insertions, 98 deletions
diff --git a/src/common/assert.h b/src/common/assert.h index 3ee07f6a2..655446f34 100644 --- a/src/common/assert.h +++ b/src/common/assert.h | |||
| @@ -30,15 +30,14 @@ __declspec(noinline, noreturn) | |||
| 30 | #define ASSERT(_a_) \ | 30 | #define ASSERT(_a_) \ |
| 31 | do \ | 31 | do \ |
| 32 | if (!(_a_)) { \ | 32 | if (!(_a_)) { \ |
| 33 | assert_noinline_call([] { NGLOG_CRITICAL(Debug, "Assertion Failed!"); }); \ | 33 | assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \ |
| 34 | } \ | 34 | } \ |
| 35 | while (0) | 35 | while (0) |
| 36 | 36 | ||
| 37 | #define ASSERT_MSG(_a_, ...) \ | 37 | #define ASSERT_MSG(_a_, ...) \ |
| 38 | do \ | 38 | do \ |
| 39 | if (!(_a_)) { \ | 39 | if (!(_a_)) { \ |
| 40 | assert_noinline_call( \ | 40 | assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \ |
| 41 | [&] { NGLOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \ | ||
| 42 | } \ | 41 | } \ |
| 43 | while (0) | 42 | while (0) |
| 44 | 43 | ||
diff --git a/src/common/common_paths.h b/src/common/common_paths.h index 0a6132dab..d03fca314 100644 --- a/src/common/common_paths.h +++ b/src/common/common_paths.h | |||
| @@ -32,12 +32,15 @@ | |||
| 32 | #define SDMC_DIR "sdmc" | 32 | #define SDMC_DIR "sdmc" |
| 33 | #define NAND_DIR "nand" | 33 | #define NAND_DIR "nand" |
| 34 | #define SYSDATA_DIR "sysdata" | 34 | #define SYSDATA_DIR "sysdata" |
| 35 | #define LOG_DIR "log" | ||
| 35 | 36 | ||
| 36 | // Filenames | 37 | // Filenames |
| 37 | // Files in the directory returned by GetUserPath(D_CONFIG_IDX) | 38 | // Files in the directory returned by GetUserPath(D_CONFIG_IDX) |
| 38 | #define EMU_CONFIG "emu.ini" | 39 | #define EMU_CONFIG "emu.ini" |
| 39 | #define DEBUGGER_CONFIG "debugger.ini" | 40 | #define DEBUGGER_CONFIG "debugger.ini" |
| 40 | #define LOGGER_CONFIG "logger.ini" | 41 | #define LOGGER_CONFIG "logger.ini" |
| 42 | // Files in the directory returned by GetUserPath(D_LOGS_IDX) | ||
| 43 | #define LOG_FILE "citra_log.txt" | ||
| 41 | 44 | ||
| 42 | // Sys files | 45 | // Sys files |
| 43 | #define SHARED_FONT "shared_font.bin" | 46 | #define SHARED_FONT "shared_font.bin" |
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 2d0b81c6e..b9e1fd1f6 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -118,7 +118,7 @@ bool IsDirectory(const std::string& filename) { | |||
| 118 | #endif | 118 | #endif |
| 119 | 119 | ||
| 120 | if (result < 0) { | 120 | if (result < 0) { |
| 121 | NGLOG_DEBUG(Common_Filesystem, "stat failed on {}: {}", filename, GetLastErrorMsg()); | 121 | LOG_DEBUG(Common_Filesystem, "stat failed on {}: {}", filename, GetLastErrorMsg()); |
| 122 | return false; | 122 | return false; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| @@ -128,29 +128,29 @@ bool IsDirectory(const std::string& filename) { | |||
| 128 | // Deletes a given filename, return true on success | 128 | // Deletes a given filename, return true on success |
| 129 | // Doesn't supports deleting a directory | 129 | // Doesn't supports deleting a directory |
| 130 | bool Delete(const std::string& filename) { | 130 | bool Delete(const std::string& filename) { |
| 131 | NGLOG_TRACE(Common_Filesystem, "file {}", filename); | 131 | LOG_TRACE(Common_Filesystem, "file {}", filename); |
| 132 | 132 | ||
| 133 | // Return true because we care about the file no | 133 | // Return true because we care about the file no |
| 134 | // being there, not the actual delete. | 134 | // being there, not the actual delete. |
| 135 | if (!Exists(filename)) { | 135 | if (!Exists(filename)) { |
| 136 | NGLOG_DEBUG(Common_Filesystem, "{} does not exist", filename); | 136 | LOG_DEBUG(Common_Filesystem, "{} does not exist", filename); |
| 137 | return true; | 137 | return true; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | // We can't delete a directory | 140 | // We can't delete a directory |
| 141 | if (IsDirectory(filename)) { | 141 | if (IsDirectory(filename)) { |
| 142 | NGLOG_ERROR(Common_Filesystem, "Failed: {} is a directory", filename); | 142 | LOG_ERROR(Common_Filesystem, "Failed: {} is a directory", filename); |
| 143 | return false; | 143 | return false; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | #ifdef _WIN32 | 146 | #ifdef _WIN32 |
| 147 | if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) { | 147 | if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) { |
| 148 | NGLOG_ERROR(Common_Filesystem, "DeleteFile failed on {}: {}", filename, GetLastErrorMsg()); | 148 | LOG_ERROR(Common_Filesystem, "DeleteFile failed on {}: {}", filename, GetLastErrorMsg()); |
| 149 | return false; | 149 | return false; |
| 150 | } | 150 | } |
| 151 | #else | 151 | #else |
| 152 | if (unlink(filename.c_str()) == -1) { | 152 | if (unlink(filename.c_str()) == -1) { |
| 153 | NGLOG_ERROR(Common_Filesystem, "unlink failed on {}: {}", filename, GetLastErrorMsg()); | 153 | LOG_ERROR(Common_Filesystem, "unlink failed on {}: {}", filename, GetLastErrorMsg()); |
| 154 | return false; | 154 | return false; |
| 155 | } | 155 | } |
| 156 | #endif | 156 | #endif |
| @@ -160,16 +160,16 @@ bool Delete(const std::string& filename) { | |||
| 160 | 160 | ||
| 161 | // Returns true if successful, or path already exists. | 161 | // Returns true if successful, or path already exists. |
| 162 | bool CreateDir(const std::string& path) { | 162 | bool CreateDir(const std::string& path) { |
| 163 | NGLOG_TRACE(Common_Filesystem, "directory {}", path); | 163 | LOG_TRACE(Common_Filesystem, "directory {}", path); |
| 164 | #ifdef _WIN32 | 164 | #ifdef _WIN32 |
| 165 | if (::CreateDirectoryW(Common::UTF8ToUTF16W(path).c_str(), nullptr)) | 165 | if (::CreateDirectoryW(Common::UTF8ToUTF16W(path).c_str(), nullptr)) |
| 166 | return true; | 166 | return true; |
| 167 | DWORD error = GetLastError(); | 167 | DWORD error = GetLastError(); |
| 168 | if (error == ERROR_ALREADY_EXISTS) { | 168 | if (error == ERROR_ALREADY_EXISTS) { |
| 169 | NGLOG_DEBUG(Common_Filesystem, "CreateDirectory failed on {}: already exists", path); | 169 | LOG_DEBUG(Common_Filesystem, "CreateDirectory failed on {}: already exists", path); |
| 170 | return true; | 170 | return true; |
| 171 | } | 171 | } |
| 172 | NGLOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error); | 172 | LOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error); |
| 173 | return false; | 173 | return false; |
| 174 | #else | 174 | #else |
| 175 | if (mkdir(path.c_str(), 0755) == 0) | 175 | if (mkdir(path.c_str(), 0755) == 0) |
| @@ -178,11 +178,11 @@ bool CreateDir(const std::string& path) { | |||
| 178 | int err = errno; | 178 | int err = errno; |
| 179 | 179 | ||
| 180 | if (err == EEXIST) { | 180 | if (err == EEXIST) { |
| 181 | NGLOG_DEBUG(Common_Filesystem, "mkdir failed on {}: already exists", path); | 181 | LOG_DEBUG(Common_Filesystem, "mkdir failed on {}: already exists", path); |
| 182 | return true; | 182 | return true; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | NGLOG_ERROR(Common_Filesystem, "mkdir failed on {}: {}", path, strerror(err)); | 185 | LOG_ERROR(Common_Filesystem, "mkdir failed on {}: {}", path, strerror(err)); |
| 186 | return false; | 186 | return false; |
| 187 | #endif | 187 | #endif |
| 188 | } | 188 | } |
| @@ -190,10 +190,10 @@ bool CreateDir(const std::string& path) { | |||
| 190 | // Creates the full path of fullPath returns true on success | 190 | // Creates the full path of fullPath returns true on success |
| 191 | bool CreateFullPath(const std::string& fullPath) { | 191 | bool CreateFullPath(const std::string& fullPath) { |
| 192 | int panicCounter = 100; | 192 | int panicCounter = 100; |
| 193 | NGLOG_TRACE(Common_Filesystem, "path {}", fullPath); | 193 | LOG_TRACE(Common_Filesystem, "path {}", fullPath); |
| 194 | 194 | ||
| 195 | if (FileUtil::Exists(fullPath)) { | 195 | if (FileUtil::Exists(fullPath)) { |
| 196 | NGLOG_DEBUG(Common_Filesystem, "path exists {}", fullPath); | 196 | LOG_DEBUG(Common_Filesystem, "path exists {}", fullPath); |
| 197 | return true; | 197 | return true; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| @@ -209,14 +209,14 @@ bool CreateFullPath(const std::string& fullPath) { | |||
| 209 | // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") | 209 | // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") |
| 210 | std::string const subPath(fullPath.substr(0, position + 1)); | 210 | std::string const subPath(fullPath.substr(0, position + 1)); |
| 211 | if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) { | 211 | if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) { |
| 212 | NGLOG_ERROR(Common, "CreateFullPath: directory creation failed"); | 212 | LOG_ERROR(Common, "CreateFullPath: directory creation failed"); |
| 213 | return false; | 213 | return false; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | // A safety check | 216 | // A safety check |
| 217 | panicCounter--; | 217 | panicCounter--; |
| 218 | if (panicCounter <= 0) { | 218 | if (panicCounter <= 0) { |
| 219 | NGLOG_ERROR(Common, "CreateFullPath: directory structure is too deep"); | 219 | LOG_ERROR(Common, "CreateFullPath: directory structure is too deep"); |
| 220 | return false; | 220 | return false; |
| 221 | } | 221 | } |
| 222 | position++; | 222 | position++; |
| @@ -225,11 +225,11 @@ bool CreateFullPath(const std::string& fullPath) { | |||
| 225 | 225 | ||
| 226 | // Deletes a directory filename, returns true on success | 226 | // Deletes a directory filename, returns true on success |
| 227 | bool DeleteDir(const std::string& filename) { | 227 | bool DeleteDir(const std::string& filename) { |
| 228 | NGLOG_TRACE(Common_Filesystem, "directory {}", filename); | 228 | LOG_TRACE(Common_Filesystem, "directory {}", filename); |
| 229 | 229 | ||
| 230 | // check if a directory | 230 | // check if a directory |
| 231 | if (!FileUtil::IsDirectory(filename)) { | 231 | if (!FileUtil::IsDirectory(filename)) { |
| 232 | NGLOG_ERROR(Common_Filesystem, "Not a directory {}", filename); | 232 | LOG_ERROR(Common_Filesystem, "Not a directory {}", filename); |
| 233 | return false; | 233 | return false; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| @@ -240,14 +240,14 @@ bool DeleteDir(const std::string& filename) { | |||
| 240 | if (rmdir(filename.c_str()) == 0) | 240 | if (rmdir(filename.c_str()) == 0) |
| 241 | return true; | 241 | return true; |
| 242 | #endif | 242 | #endif |
| 243 | NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); | 243 | LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); |
| 244 | 244 | ||
| 245 | return false; | 245 | return false; |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | // renames file srcFilename to destFilename, returns true on success | 248 | // renames file srcFilename to destFilename, returns true on success |
| 249 | bool Rename(const std::string& srcFilename, const std::string& destFilename) { | 249 | bool Rename(const std::string& srcFilename, const std::string& destFilename) { |
| 250 | NGLOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); | 250 | LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); |
| 251 | #ifdef _WIN32 | 251 | #ifdef _WIN32 |
| 252 | if (_wrename(Common::UTF8ToUTF16W(srcFilename).c_str(), | 252 | if (_wrename(Common::UTF8ToUTF16W(srcFilename).c_str(), |
| 253 | Common::UTF8ToUTF16W(destFilename).c_str()) == 0) | 253 | Common::UTF8ToUTF16W(destFilename).c_str()) == 0) |
| @@ -256,21 +256,21 @@ bool Rename(const std::string& srcFilename, const std::string& destFilename) { | |||
| 256 | if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) | 256 | if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) |
| 257 | return true; | 257 | return true; |
| 258 | #endif | 258 | #endif |
| 259 | NGLOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename, | 259 | LOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename, |
| 260 | GetLastErrorMsg()); | 260 | GetLastErrorMsg()); |
| 261 | return false; | 261 | return false; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | // copies file srcFilename to destFilename, returns true on success | 264 | // copies file srcFilename to destFilename, returns true on success |
| 265 | bool Copy(const std::string& srcFilename, const std::string& destFilename) { | 265 | bool Copy(const std::string& srcFilename, const std::string& destFilename) { |
| 266 | NGLOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); | 266 | LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); |
| 267 | #ifdef _WIN32 | 267 | #ifdef _WIN32 |
| 268 | if (CopyFileW(Common::UTF8ToUTF16W(srcFilename).c_str(), | 268 | if (CopyFileW(Common::UTF8ToUTF16W(srcFilename).c_str(), |
| 269 | Common::UTF8ToUTF16W(destFilename).c_str(), FALSE)) | 269 | Common::UTF8ToUTF16W(destFilename).c_str(), FALSE)) |
| 270 | return true; | 270 | return true; |
| 271 | 271 | ||
| 272 | NGLOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename, | 272 | LOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename, |
| 273 | GetLastErrorMsg()); | 273 | GetLastErrorMsg()); |
| 274 | return false; | 274 | return false; |
| 275 | #else | 275 | #else |
| 276 | 276 | ||
| @@ -282,8 +282,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { | |||
| 282 | // Open input file | 282 | // Open input file |
| 283 | FILE* input = fopen(srcFilename.c_str(), "rb"); | 283 | FILE* input = fopen(srcFilename.c_str(), "rb"); |
| 284 | if (!input) { | 284 | if (!input) { |
| 285 | NGLOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename, | 285 | LOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename, |
| 286 | destFilename, GetLastErrorMsg()); | 286 | destFilename, GetLastErrorMsg()); |
| 287 | return false; | 287 | return false; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| @@ -291,8 +291,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { | |||
| 291 | FILE* output = fopen(destFilename.c_str(), "wb"); | 291 | FILE* output = fopen(destFilename.c_str(), "wb"); |
| 292 | if (!output) { | 292 | if (!output) { |
| 293 | fclose(input); | 293 | fclose(input); |
| 294 | NGLOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename, | 294 | LOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename, |
| 295 | destFilename, GetLastErrorMsg()); | 295 | destFilename, GetLastErrorMsg()); |
| 296 | return false; | 296 | return false; |
| 297 | } | 297 | } |
| 298 | 298 | ||
| @@ -302,8 +302,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { | |||
| 302 | size_t rnum = fread(buffer, sizeof(char), BSIZE, input); | 302 | size_t rnum = fread(buffer, sizeof(char), BSIZE, input); |
| 303 | if (rnum != BSIZE) { | 303 | if (rnum != BSIZE) { |
| 304 | if (ferror(input) != 0) { | 304 | if (ferror(input) != 0) { |
| 305 | NGLOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}", | 305 | LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}", |
| 306 | srcFilename, destFilename, GetLastErrorMsg()); | 306 | srcFilename, destFilename, GetLastErrorMsg()); |
| 307 | goto bail; | 307 | goto bail; |
| 308 | } | 308 | } |
| 309 | } | 309 | } |
| @@ -311,8 +311,8 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { | |||
| 311 | // write output | 311 | // write output |
| 312 | size_t wnum = fwrite(buffer, sizeof(char), rnum, output); | 312 | size_t wnum = fwrite(buffer, sizeof(char), rnum, output); |
| 313 | if (wnum != rnum) { | 313 | if (wnum != rnum) { |
| 314 | NGLOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename, | 314 | LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename, |
| 315 | destFilename, GetLastErrorMsg()); | 315 | destFilename, GetLastErrorMsg()); |
| 316 | goto bail; | 316 | goto bail; |
| 317 | } | 317 | } |
| 318 | } | 318 | } |
| @@ -332,12 +332,12 @@ bail: | |||
| 332 | // Returns the size of filename (64bit) | 332 | // Returns the size of filename (64bit) |
| 333 | u64 GetSize(const std::string& filename) { | 333 | u64 GetSize(const std::string& filename) { |
| 334 | if (!Exists(filename)) { | 334 | if (!Exists(filename)) { |
| 335 | NGLOG_ERROR(Common_Filesystem, "failed {}: No such file", filename); | 335 | LOG_ERROR(Common_Filesystem, "failed {}: No such file", filename); |
| 336 | return 0; | 336 | return 0; |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | if (IsDirectory(filename)) { | 339 | if (IsDirectory(filename)) { |
| 340 | NGLOG_ERROR(Common_Filesystem, "failed {}: is a directory", filename); | 340 | LOG_ERROR(Common_Filesystem, "failed {}: is a directory", filename); |
| 341 | return 0; | 341 | return 0; |
| 342 | } | 342 | } |
| 343 | 343 | ||
| @@ -348,11 +348,11 @@ u64 GetSize(const std::string& filename) { | |||
| 348 | if (stat(filename.c_str(), &buf) == 0) | 348 | if (stat(filename.c_str(), &buf) == 0) |
| 349 | #endif | 349 | #endif |
| 350 | { | 350 | { |
| 351 | NGLOG_TRACE(Common_Filesystem, "{}: {}", filename, buf.st_size); | 351 | LOG_TRACE(Common_Filesystem, "{}: {}", filename, buf.st_size); |
| 352 | return buf.st_size; | 352 | return buf.st_size; |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | NGLOG_ERROR(Common_Filesystem, "Stat failed {}: {}", filename, GetLastErrorMsg()); | 355 | LOG_ERROR(Common_Filesystem, "Stat failed {}: {}", filename, GetLastErrorMsg()); |
| 356 | return 0; | 356 | return 0; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| @@ -360,7 +360,7 @@ u64 GetSize(const std::string& filename) { | |||
| 360 | u64 GetSize(const int fd) { | 360 | u64 GetSize(const int fd) { |
| 361 | struct stat buf; | 361 | struct stat buf; |
| 362 | if (fstat(fd, &buf) != 0) { | 362 | if (fstat(fd, &buf) != 0) { |
| 363 | NGLOG_ERROR(Common_Filesystem, "GetSize: stat failed {}: {}", fd, GetLastErrorMsg()); | 363 | LOG_ERROR(Common_Filesystem, "GetSize: stat failed {}: {}", fd, GetLastErrorMsg()); |
| 364 | return 0; | 364 | return 0; |
| 365 | } | 365 | } |
| 366 | return buf.st_size; | 366 | return buf.st_size; |
| @@ -371,14 +371,12 @@ u64 GetSize(FILE* f) { | |||
| 371 | // can't use off_t here because it can be 32-bit | 371 | // can't use off_t here because it can be 32-bit |
| 372 | u64 pos = ftello(f); | 372 | u64 pos = ftello(f); |
| 373 | if (fseeko(f, 0, SEEK_END) != 0) { | 373 | if (fseeko(f, 0, SEEK_END) != 0) { |
| 374 | NGLOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f), | 374 | LOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f), GetLastErrorMsg()); |
| 375 | GetLastErrorMsg()); | ||
| 376 | return 0; | 375 | return 0; |
| 377 | } | 376 | } |
| 378 | u64 size = ftello(f); | 377 | u64 size = ftello(f); |
| 379 | if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) { | 378 | if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) { |
| 380 | NGLOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f), | 379 | LOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f), GetLastErrorMsg()); |
| 381 | GetLastErrorMsg()); | ||
| 382 | return 0; | 380 | return 0; |
| 383 | } | 381 | } |
| 384 | return size; | 382 | return size; |
| @@ -386,10 +384,10 @@ u64 GetSize(FILE* f) { | |||
| 386 | 384 | ||
| 387 | // creates an empty file filename, returns true on success | 385 | // creates an empty file filename, returns true on success |
| 388 | bool CreateEmptyFile(const std::string& filename) { | 386 | bool CreateEmptyFile(const std::string& filename) { |
| 389 | NGLOG_TRACE(Common_Filesystem, "{}", filename); | 387 | LOG_TRACE(Common_Filesystem, "{}", filename); |
| 390 | 388 | ||
| 391 | if (!FileUtil::IOFile(filename, "wb")) { | 389 | if (!FileUtil::IOFile(filename, "wb")) { |
| 392 | NGLOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); | 390 | LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); |
| 393 | return false; | 391 | return false; |
| 394 | } | 392 | } |
| 395 | 393 | ||
| @@ -398,7 +396,7 @@ bool CreateEmptyFile(const std::string& filename) { | |||
| 398 | 396 | ||
| 399 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directory, | 397 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string& directory, |
| 400 | DirectoryEntryCallable callback) { | 398 | DirectoryEntryCallable callback) { |
| 401 | NGLOG_TRACE(Common_Filesystem, "directory {}", directory); | 399 | LOG_TRACE(Common_Filesystem, "directory {}", directory); |
| 402 | 400 | ||
| 403 | // How many files + directories we found | 401 | // How many files + directories we found |
| 404 | unsigned found_entries = 0; | 402 | unsigned found_entries = 0; |
| @@ -556,7 +554,7 @@ std::string GetCurrentDir() { | |||
| 556 | char* dir; | 554 | char* dir; |
| 557 | if (!(dir = getcwd(nullptr, 0))) { | 555 | if (!(dir = getcwd(nullptr, 0))) { |
| 558 | #endif | 556 | #endif |
| 559 | NGLOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); | 557 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); |
| 560 | return nullptr; | 558 | return nullptr; |
| 561 | } | 559 | } |
| 562 | #ifdef _WIN32 | 560 | #ifdef _WIN32 |
| @@ -676,7 +674,7 @@ std::string GetSysDirectory() { | |||
| 676 | #endif | 674 | #endif |
| 677 | sysDir += DIR_SEP; | 675 | sysDir += DIR_SEP; |
| 678 | 676 | ||
| 679 | NGLOG_DEBUG(Common_Filesystem, "Setting to {}:", sysDir); | 677 | LOG_DEBUG(Common_Filesystem, "Setting to {}:", sysDir); |
| 680 | return sysDir; | 678 | return sysDir; |
| 681 | } | 679 | } |
| 682 | 680 | ||
| @@ -692,7 +690,7 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new | |||
| 692 | if (!FileUtil::IsDirectory(paths[D_USER_IDX])) { | 690 | if (!FileUtil::IsDirectory(paths[D_USER_IDX])) { |
| 693 | paths[D_USER_IDX] = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP; | 691 | paths[D_USER_IDX] = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP; |
| 694 | } else { | 692 | } else { |
| 695 | NGLOG_INFO(Common_Filesystem, "Using the local user directory"); | 693 | LOG_INFO(Common_Filesystem, "Using the local user directory"); |
| 696 | } | 694 | } |
| 697 | 695 | ||
| 698 | paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; | 696 | paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; |
| @@ -715,11 +713,13 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string& new | |||
| 715 | paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; | 713 | paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; |
| 716 | paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; | 714 | paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; |
| 717 | paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; | 715 | paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; |
| 716 | // TODO: Put the logs in a better location for each OS | ||
| 717 | paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOG_DIR DIR_SEP; | ||
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | if (!newPath.empty()) { | 720 | if (!newPath.empty()) { |
| 721 | if (!FileUtil::IsDirectory(newPath)) { | 721 | if (!FileUtil::IsDirectory(newPath)) { |
| 722 | NGLOG_ERROR(Common_Filesystem, "Invalid path specified {}", newPath); | 722 | LOG_ERROR(Common_Filesystem, "Invalid path specified {}", newPath); |
| 723 | return paths[DirIDX]; | 723 | return paths[DirIDX]; |
| 724 | } else { | 724 | } else { |
| 725 | paths[DirIDX] = newPath; | 725 | paths[DirIDX] = newPath; |
| @@ -801,8 +801,8 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam | |||
| 801 | 801 | ||
| 802 | IOFile::IOFile() {} | 802 | IOFile::IOFile() {} |
| 803 | 803 | ||
| 804 | IOFile::IOFile(const std::string& filename, const char openmode[]) { | 804 | IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { |
| 805 | Open(filename, openmode); | 805 | Open(filename, openmode, flags); |
| 806 | } | 806 | } |
| 807 | 807 | ||
| 808 | IOFile::~IOFile() { | 808 | IOFile::~IOFile() { |
| @@ -823,11 +823,16 @@ void IOFile::Swap(IOFile& other) noexcept { | |||
| 823 | std::swap(m_good, other.m_good); | 823 | std::swap(m_good, other.m_good); |
| 824 | } | 824 | } |
| 825 | 825 | ||
| 826 | bool IOFile::Open(const std::string& filename, const char openmode[]) { | 826 | bool IOFile::Open(const std::string& filename, const char openmode[], int flags) { |
| 827 | Close(); | 827 | Close(); |
| 828 | #ifdef _WIN32 | 828 | #ifdef _WIN32 |
| 829 | _wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(), | 829 | if (flags != 0) { |
| 830 | Common::UTF8ToUTF16W(openmode).c_str()); | 830 | m_file = _wfsopen(Common::UTF8ToUTF16W(filename).c_str(), |
| 831 | Common::UTF8ToUTF16W(openmode).c_str(), flags); | ||
| 832 | } else { | ||
| 833 | _wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(), | ||
| 834 | Common::UTF8ToUTF16W(openmode).c_str()); | ||
| 835 | } | ||
| 831 | #else | 836 | #else |
| 832 | m_file = fopen(filename.c_str(), openmode); | 837 | m_file = fopen(filename.c_str(), openmode); |
| 833 | #endif | 838 | #endif |
diff --git a/src/common/file_util.h b/src/common/file_util.h index fc6b3ea46..5bc7fbf7c 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -156,7 +156,10 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam | |||
| 156 | class IOFile : public NonCopyable { | 156 | class IOFile : public NonCopyable { |
| 157 | public: | 157 | public: |
| 158 | IOFile(); | 158 | IOFile(); |
| 159 | IOFile(const std::string& filename, const char openmode[]); | 159 | // flags is used for windows specific file open mode flags, which |
| 160 | // allows yuzu to open the logs in shared write mode, so that the file | ||
| 161 | // isn't considered "locked" while yuzu is open and people can open the log file and view it | ||
| 162 | IOFile(const std::string& filename, const char openmode[], int flags = 0); | ||
| 160 | 163 | ||
| 161 | ~IOFile(); | 164 | ~IOFile(); |
| 162 | 165 | ||
| @@ -165,7 +168,7 @@ public: | |||
| 165 | 168 | ||
| 166 | void Swap(IOFile& other) noexcept; | 169 | void Swap(IOFile& other) noexcept; |
| 167 | 170 | ||
| 168 | bool Open(const std::string& filename, const char openmode[]); | 171 | bool Open(const std::string& filename, const char openmode[], int flags = 0); |
| 169 | bool Close(); | 172 | bool Close(); |
| 170 | 173 | ||
| 171 | template <typename T> | 174 | template <typename T> |
| @@ -220,6 +223,10 @@ public: | |||
| 220 | return WriteArray(&object, 1); | 223 | return WriteArray(&object, 1); |
| 221 | } | 224 | } |
| 222 | 225 | ||
| 226 | size_t WriteString(const std::string& str) { | ||
| 227 | return WriteArray(str.c_str(), str.length()); | ||
| 228 | } | ||
| 229 | |||
| 223 | bool IsOpen() const { | 230 | bool IsOpen() const { |
| 224 | return nullptr != m_file; | 231 | return nullptr != m_file; |
| 225 | } | 232 | } |
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index c26b20062..242914c6a 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -2,16 +2,145 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <utility> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 7 | #include <chrono> | ||
| 8 | #include <condition_variable> | ||
| 9 | #include <memory> | ||
| 10 | #include <thread> | ||
| 11 | #ifdef _WIN32 | ||
| 12 | #include <share.h> // For _SH_DENYWR | ||
| 13 | #else | ||
| 14 | #define _SH_DENYWR 0 | ||
| 15 | #endif | ||
| 6 | #include "common/assert.h" | 16 | #include "common/assert.h" |
| 17 | #include "common/common_funcs.h" // snprintf compatibility define | ||
| 7 | #include "common/logging/backend.h" | 18 | #include "common/logging/backend.h" |
| 8 | #include "common/logging/filter.h" | ||
| 9 | #include "common/logging/log.h" | 19 | #include "common/logging/log.h" |
| 10 | #include "common/logging/text_formatter.h" | 20 | #include "common/logging/text_formatter.h" |
| 11 | #include "common/string_util.h" | 21 | #include "common/string_util.h" |
| 22 | #include "common/threadsafe_queue.h" | ||
| 12 | 23 | ||
| 13 | namespace Log { | 24 | namespace Log { |
| 14 | 25 | ||
| 26 | /** | ||
| 27 | * Static state as a singleton. | ||
| 28 | */ | ||
| 29 | class Impl { | ||
| 30 | public: | ||
| 31 | static Impl& Instance() { | ||
| 32 | static Impl backend; | ||
| 33 | return backend; | ||
| 34 | } | ||
| 35 | |||
| 36 | Impl(Impl const&) = delete; | ||
| 37 | const Impl& operator=(Impl const&) = delete; | ||
| 38 | |||
| 39 | void PushEntry(Entry e) { | ||
| 40 | std::lock_guard<std::mutex> lock(message_mutex); | ||
| 41 | message_queue.Push(std::move(e)); | ||
| 42 | message_cv.notify_one(); | ||
| 43 | } | ||
| 44 | |||
| 45 | void AddBackend(std::unique_ptr<Backend> backend) { | ||
| 46 | std::lock_guard<std::mutex> lock(writing_mutex); | ||
| 47 | backends.push_back(std::move(backend)); | ||
| 48 | } | ||
| 49 | |||
| 50 | void RemoveBackend(const std::string& backend_name) { | ||
| 51 | std::lock_guard<std::mutex> lock(writing_mutex); | ||
| 52 | auto it = std::remove_if(backends.begin(), backends.end(), [&backend_name](const auto& i) { | ||
| 53 | return !strcmp(i->GetName(), backend_name.c_str()); | ||
| 54 | }); | ||
| 55 | backends.erase(it, backends.end()); | ||
| 56 | } | ||
| 57 | |||
| 58 | const Filter& GetGlobalFilter() const { | ||
| 59 | return filter; | ||
| 60 | } | ||
| 61 | |||
| 62 | void SetGlobalFilter(const Filter& f) { | ||
| 63 | filter = f; | ||
| 64 | } | ||
| 65 | |||
| 66 | Backend* GetBackend(const std::string& backend_name) { | ||
| 67 | auto it = std::find_if(backends.begin(), backends.end(), [&backend_name](const auto& i) { | ||
| 68 | return !strcmp(i->GetName(), backend_name.c_str()); | ||
| 69 | }); | ||
| 70 | if (it == backends.end()) | ||
| 71 | return nullptr; | ||
| 72 | return it->get(); | ||
| 73 | } | ||
| 74 | |||
| 75 | private: | ||
| 76 | Impl() { | ||
| 77 | backend_thread = std::thread([&] { | ||
| 78 | Entry entry; | ||
| 79 | auto write_logs = [&](Entry& e) { | ||
| 80 | std::lock_guard<std::mutex> lock(writing_mutex); | ||
| 81 | for (const auto& backend : backends) { | ||
| 82 | backend->Write(e); | ||
| 83 | } | ||
| 84 | }; | ||
| 85 | while (true) { | ||
| 86 | std::unique_lock<std::mutex> lock(message_mutex); | ||
| 87 | message_cv.wait(lock, [&] { return !running || message_queue.Pop(entry); }); | ||
| 88 | if (!running) { | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | write_logs(entry); | ||
| 92 | } | ||
| 93 | // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a case | ||
| 94 | // where a system is repeatedly spamming logs even on close. | ||
| 95 | constexpr int MAX_LOGS_TO_WRITE = 100; | ||
| 96 | int logs_written = 0; | ||
| 97 | while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) { | ||
| 98 | write_logs(entry); | ||
| 99 | } | ||
| 100 | }); | ||
| 101 | } | ||
| 102 | |||
| 103 | ~Impl() { | ||
| 104 | running = false; | ||
| 105 | message_cv.notify_one(); | ||
| 106 | backend_thread.join(); | ||
| 107 | } | ||
| 108 | |||
| 109 | std::atomic_bool running{true}; | ||
| 110 | std::mutex message_mutex, writing_mutex; | ||
| 111 | std::condition_variable message_cv; | ||
| 112 | std::thread backend_thread; | ||
| 113 | std::vector<std::unique_ptr<Backend>> backends; | ||
| 114 | Common::MPSCQueue<Log::Entry> message_queue; | ||
| 115 | Filter filter; | ||
| 116 | }; | ||
| 117 | |||
| 118 | void ConsoleBackend::Write(const Entry& entry) { | ||
| 119 | PrintMessage(entry); | ||
| 120 | } | ||
| 121 | |||
| 122 | void ColorConsoleBackend::Write(const Entry& entry) { | ||
| 123 | PrintColoredMessage(entry); | ||
| 124 | } | ||
| 125 | |||
| 126 | // _SH_DENYWR allows read only access to the file for other programs. | ||
| 127 | // It is #defined to 0 on other platforms | ||
| 128 | FileBackend::FileBackend(const std::string& filename) | ||
| 129 | : file(filename, "w", _SH_DENYWR), bytes_written(0) {} | ||
| 130 | |||
| 131 | void FileBackend::Write(const Entry& entry) { | ||
| 132 | // prevent logs from going over the maximum size (in case its spamming and the user doesn't | ||
| 133 | // know) | ||
| 134 | constexpr size_t MAX_BYTES_WRITTEN = 50 * 1024L * 1024L; | ||
| 135 | if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) { | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | bytes_written += file.WriteString(FormatLogMessage(entry) + '\n'); | ||
| 139 | if (entry.log_level >= Level::Error) { | ||
| 140 | file.Flush(); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 15 | /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. | 144 | /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. |
| 16 | #define ALL_LOG_CLASSES() \ | 145 | #define ALL_LOG_CLASSES() \ |
| 17 | CLS(Log) \ | 146 | CLS(Log) \ |
| @@ -125,20 +254,32 @@ Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsign | |||
| 125 | return entry; | 254 | return entry; |
| 126 | } | 255 | } |
| 127 | 256 | ||
| 128 | static Filter* filter = nullptr; | 257 | void SetGlobalFilter(const Filter& filter) { |
| 258 | Impl::Instance().SetGlobalFilter(filter); | ||
| 259 | } | ||
| 260 | |||
| 261 | void AddBackend(std::unique_ptr<Backend> backend) { | ||
| 262 | Impl::Instance().AddBackend(std::move(backend)); | ||
| 263 | } | ||
| 129 | 264 | ||
| 130 | void SetFilter(Filter* new_filter) { | 265 | void RemoveBackend(const std::string& backend_name) { |
| 131 | filter = new_filter; | 266 | Impl::Instance().RemoveBackend(backend_name); |
| 267 | } | ||
| 268 | |||
| 269 | Backend* GetBackend(const std::string& backend_name) { | ||
| 270 | return Impl::Instance().GetBackend(backend_name); | ||
| 132 | } | 271 | } |
| 133 | 272 | ||
| 134 | void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | 273 | void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, |
| 135 | unsigned int line_num, const char* function, const char* format, | 274 | unsigned int line_num, const char* function, const char* format, |
| 136 | const fmt::format_args& args) { | 275 | const fmt::format_args& args) { |
| 137 | if (filter && !filter->CheckMessage(log_class, log_level)) | 276 | auto filter = Impl::Instance().GetGlobalFilter(); |
| 277 | if (!filter.CheckMessage(log_class, log_level)) | ||
| 138 | return; | 278 | return; |
| 279 | |||
| 139 | Entry entry = | 280 | Entry entry = |
| 140 | CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); | 281 | CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); |
| 141 | 282 | ||
| 142 | PrintColoredMessage(entry); | 283 | Impl::Instance().PushEntry(std::move(entry)); |
| 143 | } | 284 | } |
| 144 | } // namespace Log | 285 | } // namespace Log \ No newline at end of file |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 7e81efb23..57cdf6b2d 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -1,13 +1,15 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | |||
| 5 | #pragma once | 4 | #pragma once |
| 6 | 5 | ||
| 7 | #include <chrono> | 6 | #include <chrono> |
| 8 | #include <cstdarg> | 7 | #include <cstdarg> |
| 8 | #include <memory> | ||
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | #include "common/file_util.h" | ||
| 12 | #include "common/logging/filter.h" | ||
| 11 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 12 | 14 | ||
| 13 | namespace Log { | 15 | namespace Log { |
| @@ -35,6 +37,80 @@ struct Entry { | |||
| 35 | }; | 37 | }; |
| 36 | 38 | ||
| 37 | /** | 39 | /** |
| 40 | * Interface for logging backends. As loggers can be created and removed at runtime, this can be | ||
| 41 | * used by a frontend for adding a custom logging backend as needed | ||
| 42 | */ | ||
| 43 | class Backend { | ||
| 44 | public: | ||
| 45 | virtual ~Backend() = default; | ||
| 46 | virtual void SetFilter(const Filter& new_filter) { | ||
| 47 | filter = new_filter; | ||
| 48 | } | ||
| 49 | virtual const char* GetName() const = 0; | ||
| 50 | virtual void Write(const Entry& entry) = 0; | ||
| 51 | |||
| 52 | private: | ||
| 53 | Filter filter; | ||
| 54 | }; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Backend that writes to stderr without any color commands | ||
| 58 | */ | ||
| 59 | class ConsoleBackend : public Backend { | ||
| 60 | public: | ||
| 61 | static const char* Name() { | ||
| 62 | return "console"; | ||
| 63 | } | ||
| 64 | const char* GetName() const override { | ||
| 65 | return Name(); | ||
| 66 | } | ||
| 67 | void Write(const Entry& entry) override; | ||
| 68 | }; | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Backend that writes to stderr and with color | ||
| 72 | */ | ||
| 73 | class ColorConsoleBackend : public Backend { | ||
| 74 | public: | ||
| 75 | static const char* Name() { | ||
| 76 | return "color_console"; | ||
| 77 | } | ||
| 78 | |||
| 79 | const char* GetName() const override { | ||
| 80 | return Name(); | ||
| 81 | } | ||
| 82 | void Write(const Entry& entry) override; | ||
| 83 | }; | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Backend that writes to a file passed into the constructor | ||
| 87 | */ | ||
| 88 | class FileBackend : public Backend { | ||
| 89 | public: | ||
| 90 | explicit FileBackend(const std::string& filename); | ||
| 91 | |||
| 92 | static const char* Name() { | ||
| 93 | return "file"; | ||
| 94 | } | ||
| 95 | |||
| 96 | const char* GetName() const override { | ||
| 97 | return Name(); | ||
| 98 | } | ||
| 99 | |||
| 100 | void Write(const Entry& entry) override; | ||
| 101 | |||
| 102 | private: | ||
| 103 | FileUtil::IOFile file; | ||
| 104 | size_t bytes_written; | ||
| 105 | }; | ||
| 106 | |||
| 107 | void AddBackend(std::unique_ptr<Backend> backend); | ||
| 108 | |||
| 109 | void RemoveBackend(const std::string& backend_name); | ||
| 110 | |||
| 111 | Backend* GetBackend(const std::string& backend_name); | ||
| 112 | |||
| 113 | /** | ||
| 38 | * Returns the name of the passed log class as a C-string. Subclasses are separated by periods | 114 | * Returns the name of the passed log class as a C-string. Subclasses are separated by periods |
| 39 | * instead of underscores as in the enumeration. | 115 | * instead of underscores as in the enumeration. |
| 40 | */ | 116 | */ |
| @@ -49,5 +125,10 @@ const char* GetLevelName(Level log_level); | |||
| 49 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | 125 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, |
| 50 | const char* function, std::string message); | 126 | const char* function, std::string message); |
| 51 | 127 | ||
| 52 | void SetFilter(Filter* filter); | 128 | /** |
| 53 | } // namespace Log | 129 | * The global filter will prevent any messages from even being processed if they are filtered. Each |
| 130 | * backend can have a filter, but if the level is lower than the global filter, the backend will | ||
| 131 | * never get the message | ||
| 132 | */ | ||
| 133 | void SetGlobalFilter(const Filter& filter); | ||
| 134 | } // namespace Log \ No newline at end of file | ||
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 428723dce..4e783a577 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp | |||
| @@ -65,14 +65,14 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin, | |||
| 65 | const std::string::const_iterator end) { | 65 | const std::string::const_iterator end) { |
| 66 | auto level_separator = std::find(begin, end, ':'); | 66 | auto level_separator = std::find(begin, end, ':'); |
| 67 | if (level_separator == end) { | 67 | if (level_separator == end) { |
| 68 | NGLOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: %s", | 68 | LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}", |
| 69 | std::string(begin, end).c_str()); | 69 | std::string(begin, end)); |
| 70 | return false; | 70 | return false; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | const Level level = GetLevelByName(level_separator + 1, end); | 73 | const Level level = GetLevelByName(level_separator + 1, end); |
| 74 | if (level == Level::Count) { | 74 | if (level == Level::Count) { |
| 75 | NGLOG_ERROR(Log, "Unknown log level in filter: %s", std::string(begin, end).c_str()); | 75 | LOG_ERROR(Log, "Unknown log level in filter: {}", std::string(begin, end)); |
| 76 | return false; | 76 | return false; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| @@ -83,7 +83,7 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin, | |||
| 83 | 83 | ||
| 84 | const Class log_class = GetClassByName(begin, level_separator); | 84 | const Class log_class = GetClassByName(begin, level_separator); |
| 85 | if (log_class == Class::Count) { | 85 | if (log_class == Class::Count) { |
| 86 | NGLOG_ERROR(Log, "Unknown log class in filter: %s", std::string(begin, end).c_str()); | 86 | LOG_ERROR(Log, "Unknown log class in filter: {}", std::string(begin, end)); |
| 87 | return false; | 87 | return false; |
| 88 | } | 88 | } |
| 89 | 89 | ||
diff --git a/src/common/logging/log.h b/src/common/logging/log.h index c5015531c..e96c90e16 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h | |||
| @@ -109,25 +109,25 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig | |||
| 109 | } // namespace Log | 109 | } // namespace Log |
| 110 | 110 | ||
| 111 | #ifdef _DEBUG | 111 | #ifdef _DEBUG |
| 112 | #define NGLOG_TRACE(log_class, ...) \ | 112 | #define LOG_TRACE(log_class, ...) \ |
| 113 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, __FILE__, __LINE__, \ | 113 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, __FILE__, __LINE__, \ |
| 114 | __func__, __VA_ARGS__) | 114 | __func__, __VA_ARGS__) |
| 115 | #else | 115 | #else |
| 116 | #define NGLOG_TRACE(log_class, fmt, ...) (void(0)) | 116 | #define LOG_TRACE(log_class, fmt, ...) (void(0)) |
| 117 | #endif | 117 | #endif |
| 118 | 118 | ||
| 119 | #define NGLOG_DEBUG(log_class, ...) \ | 119 | #define LOG_DEBUG(log_class, ...) \ |
| 120 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, __FILE__, __LINE__, \ | 120 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, __FILE__, __LINE__, \ |
| 121 | __func__, __VA_ARGS__) | 121 | __func__, __VA_ARGS__) |
| 122 | #define NGLOG_INFO(log_class, ...) \ | 122 | #define LOG_INFO(log_class, ...) \ |
| 123 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, __FILE__, __LINE__, \ | 123 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, __FILE__, __LINE__, \ |
| 124 | __func__, __VA_ARGS__) | 124 | __func__, __VA_ARGS__) |
| 125 | #define NGLOG_WARNING(log_class, ...) \ | 125 | #define LOG_WARNING(log_class, ...) \ |
| 126 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, __FILE__, __LINE__, \ | 126 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, __FILE__, __LINE__, \ |
| 127 | __func__, __VA_ARGS__) | 127 | __func__, __VA_ARGS__) |
| 128 | #define NGLOG_ERROR(log_class, ...) \ | 128 | #define LOG_ERROR(log_class, ...) \ |
| 129 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, __FILE__, __LINE__, \ | 129 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, __FILE__, __LINE__, \ |
| 130 | __func__, __VA_ARGS__) | 130 | __func__, __VA_ARGS__) |
| 131 | #define NGLOG_CRITICAL(log_class, ...) \ | 131 | #define LOG_CRITICAL(log_class, ...) \ |
| 132 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, __FILE__, __LINE__, \ | 132 | ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, __FILE__, __LINE__, \ |
| 133 | __func__, __VA_ARGS__) | 133 | __func__, __VA_ARGS__) |
diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp index 4d1ec8fb9..5d89209ed 100644 --- a/src/common/memory_util.cpp +++ b/src/common/memory_util.cpp | |||
| @@ -55,7 +55,7 @@ void* AllocateExecutableMemory(size_t size, bool low) { | |||
| 55 | if (ptr == MAP_FAILED) { | 55 | if (ptr == MAP_FAILED) { |
| 56 | ptr = nullptr; | 56 | ptr = nullptr; |
| 57 | #endif | 57 | #endif |
| 58 | NGLOG_ERROR(Common_Memory, "Failed to allocate executable memory"); | 58 | LOG_ERROR(Common_Memory, "Failed to allocate executable memory"); |
| 59 | } | 59 | } |
| 60 | #if !defined(_WIN32) && defined(ARCHITECTURE_X64) && !defined(MAP_32BIT) | 60 | #if !defined(_WIN32) && defined(ARCHITECTURE_X64) && !defined(MAP_32BIT) |
| 61 | else { | 61 | else { |
| @@ -68,7 +68,7 @@ void* AllocateExecutableMemory(size_t size, bool low) { | |||
| 68 | 68 | ||
| 69 | #if EMU_ARCH_BITS == 64 | 69 | #if EMU_ARCH_BITS == 64 |
| 70 | if ((u64)ptr >= 0x80000000 && low == true) | 70 | if ((u64)ptr >= 0x80000000 && low == true) |
| 71 | NGLOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!"); | 71 | LOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!"); |
| 72 | #endif | 72 | #endif |
| 73 | 73 | ||
| 74 | return ptr; | 74 | return ptr; |
| @@ -85,7 +85,7 @@ void* AllocateMemoryPages(size_t size) { | |||
| 85 | #endif | 85 | #endif |
| 86 | 86 | ||
| 87 | if (ptr == nullptr) | 87 | if (ptr == nullptr) |
| 88 | NGLOG_ERROR(Common_Memory, "Failed to allocate raw memory"); | 88 | LOG_ERROR(Common_Memory, "Failed to allocate raw memory"); |
| 89 | 89 | ||
| 90 | return ptr; | 90 | return ptr; |
| 91 | } | 91 | } |
| @@ -99,12 +99,12 @@ void* AllocateAlignedMemory(size_t size, size_t alignment) { | |||
| 99 | ptr = memalign(alignment, size); | 99 | ptr = memalign(alignment, size); |
| 100 | #else | 100 | #else |
| 101 | if (posix_memalign(&ptr, alignment, size) != 0) | 101 | if (posix_memalign(&ptr, alignment, size) != 0) |
| 102 | NGLOG_ERROR(Common_Memory, "Failed to allocate aligned memory"); | 102 | LOG_ERROR(Common_Memory, "Failed to allocate aligned memory"); |
| 103 | #endif | 103 | #endif |
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | if (ptr == nullptr) | 106 | if (ptr == nullptr) |
| 107 | NGLOG_ERROR(Common_Memory, "Failed to allocate aligned memory"); | 107 | LOG_ERROR(Common_Memory, "Failed to allocate aligned memory"); |
| 108 | 108 | ||
| 109 | return ptr; | 109 | return ptr; |
| 110 | } | 110 | } |
| @@ -113,7 +113,7 @@ void FreeMemoryPages(void* ptr, size_t size) { | |||
| 113 | if (ptr) { | 113 | if (ptr) { |
| 114 | #ifdef _WIN32 | 114 | #ifdef _WIN32 |
| 115 | if (!VirtualFree(ptr, 0, MEM_RELEASE)) | 115 | if (!VirtualFree(ptr, 0, MEM_RELEASE)) |
| 116 | NGLOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n{}", GetLastErrorMsg()); | 116 | LOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n{}", GetLastErrorMsg()); |
| 117 | #else | 117 | #else |
| 118 | munmap(ptr, size); | 118 | munmap(ptr, size); |
| 119 | #endif | 119 | #endif |
| @@ -134,7 +134,7 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) { | |||
| 134 | #ifdef _WIN32 | 134 | #ifdef _WIN32 |
| 135 | DWORD oldValue; | 135 | DWORD oldValue; |
| 136 | if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) | 136 | if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) |
| 137 | NGLOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n{}", GetLastErrorMsg()); | 137 | LOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n{}", GetLastErrorMsg()); |
| 138 | #else | 138 | #else |
| 139 | mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); | 139 | mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); |
| 140 | #endif | 140 | #endif |
| @@ -145,7 +145,7 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) { | |||
| 145 | DWORD oldValue; | 145 | DWORD oldValue; |
| 146 | if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, | 146 | if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, |
| 147 | &oldValue)) | 147 | &oldValue)) |
| 148 | NGLOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n{}", GetLastErrorMsg()); | 148 | LOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n{}", GetLastErrorMsg()); |
| 149 | #else | 149 | #else |
| 150 | mprotect(ptr, size, | 150 | mprotect(ptr, size, |
| 151 | allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); | 151 | allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); |
diff --git a/src/common/param_package.cpp b/src/common/param_package.cpp index ab0154133..e0df430ab 100644 --- a/src/common/param_package.cpp +++ b/src/common/param_package.cpp | |||
| @@ -25,7 +25,7 @@ ParamPackage::ParamPackage(const std::string& serialized) { | |||
| 25 | std::vector<std::string> key_value; | 25 | std::vector<std::string> key_value; |
| 26 | Common::SplitString(pair, KEY_VALUE_SEPARATOR, key_value); | 26 | Common::SplitString(pair, KEY_VALUE_SEPARATOR, key_value); |
| 27 | if (key_value.size() != 2) { | 27 | if (key_value.size() != 2) { |
| 28 | NGLOG_ERROR(Common, "invalid key pair {}", pair); | 28 | LOG_ERROR(Common, "invalid key pair {}", pair); |
| 29 | continue; | 29 | continue; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| @@ -64,7 +64,7 @@ std::string ParamPackage::Serialize() const { | |||
| 64 | std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const { | 64 | std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const { |
| 65 | auto pair = data.find(key); | 65 | auto pair = data.find(key); |
| 66 | if (pair == data.end()) { | 66 | if (pair == data.end()) { |
| 67 | NGLOG_DEBUG(Common, "key '{}' not found", key); | 67 | LOG_DEBUG(Common, "key '{}' not found", key); |
| 68 | return default_value; | 68 | return default_value; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| @@ -74,14 +74,14 @@ std::string ParamPackage::Get(const std::string& key, const std::string& default | |||
| 74 | int ParamPackage::Get(const std::string& key, int default_value) const { | 74 | int ParamPackage::Get(const std::string& key, int default_value) const { |
| 75 | auto pair = data.find(key); | 75 | auto pair = data.find(key); |
| 76 | if (pair == data.end()) { | 76 | if (pair == data.end()) { |
| 77 | NGLOG_DEBUG(Common, "key '{}' not found", key); | 77 | LOG_DEBUG(Common, "key '{}' not found", key); |
| 78 | return default_value; | 78 | return default_value; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | try { | 81 | try { |
| 82 | return std::stoi(pair->second); | 82 | return std::stoi(pair->second); |
| 83 | } catch (const std::logic_error&) { | 83 | } catch (const std::logic_error&) { |
| 84 | NGLOG_ERROR(Common, "failed to convert {} to int", pair->second); | 84 | LOG_ERROR(Common, "failed to convert {} to int", pair->second); |
| 85 | return default_value; | 85 | return default_value; |
| 86 | } | 86 | } |
| 87 | } | 87 | } |
| @@ -89,14 +89,14 @@ int ParamPackage::Get(const std::string& key, int default_value) const { | |||
| 89 | float ParamPackage::Get(const std::string& key, float default_value) const { | 89 | float ParamPackage::Get(const std::string& key, float default_value) const { |
| 90 | auto pair = data.find(key); | 90 | auto pair = data.find(key); |
| 91 | if (pair == data.end()) { | 91 | if (pair == data.end()) { |
| 92 | NGLOG_DEBUG(Common, "key {} not found", key); | 92 | LOG_DEBUG(Common, "key {} not found", key); |
| 93 | return default_value; | 93 | return default_value; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | try { | 96 | try { |
| 97 | return std::stof(pair->second); | 97 | return std::stof(pair->second); |
| 98 | } catch (const std::logic_error&) { | 98 | } catch (const std::logic_error&) { |
| 99 | NGLOG_ERROR(Common, "failed to convert {} to float", pair->second); | 99 | LOG_ERROR(Common, "failed to convert {} to float", pair->second); |
| 100 | return default_value; | 100 | return default_value; |
| 101 | } | 101 | } |
| 102 | } | 102 | } |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 646400db0..ea9d8f77c 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -281,7 +281,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& | |||
| 281 | 281 | ||
| 282 | iconv_t const conv_desc = iconv_open("UTF-8", fromcode); | 282 | iconv_t const conv_desc = iconv_open("UTF-8", fromcode); |
| 283 | if ((iconv_t)(-1) == conv_desc) { | 283 | if ((iconv_t)(-1) == conv_desc) { |
| 284 | NGLOG_ERROR(Common, "Iconv initialization failure [{}]: {}", fromcode, strerror(errno)); | 284 | LOG_ERROR(Common, "Iconv initialization failure [{}]: {}", fromcode, strerror(errno)); |
| 285 | iconv_close(conv_desc); | 285 | iconv_close(conv_desc); |
| 286 | return {}; | 286 | return {}; |
| 287 | } | 287 | } |
| @@ -310,7 +310,7 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& | |||
| 310 | ++src_buffer; | 310 | ++src_buffer; |
| 311 | } | 311 | } |
| 312 | } else { | 312 | } else { |
| 313 | NGLOG_ERROR(Common, "iconv failure [{}]: {}", fromcode, strerror(errno)); | 313 | LOG_ERROR(Common, "iconv failure [{}]: {}", fromcode, strerror(errno)); |
| 314 | break; | 314 | break; |
| 315 | } | 315 | } |
| 316 | } | 316 | } |
| @@ -329,7 +329,7 @@ std::u16string UTF8ToUTF16(const std::string& input) { | |||
| 329 | 329 | ||
| 330 | iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8"); | 330 | iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8"); |
| 331 | if ((iconv_t)(-1) == conv_desc) { | 331 | if ((iconv_t)(-1) == conv_desc) { |
| 332 | NGLOG_ERROR(Common, "Iconv initialization failure [UTF-8]: {}", strerror(errno)); | 332 | LOG_ERROR(Common, "Iconv initialization failure [UTF-8]: {}", strerror(errno)); |
| 333 | iconv_close(conv_desc); | 333 | iconv_close(conv_desc); |
| 334 | return {}; | 334 | return {}; |
| 335 | } | 335 | } |
| @@ -358,7 +358,7 @@ std::u16string UTF8ToUTF16(const std::string& input) { | |||
| 358 | ++src_buffer; | 358 | ++src_buffer; |
| 359 | } | 359 | } |
| 360 | } else { | 360 | } else { |
| 361 | NGLOG_ERROR(Common, "iconv failure [UTF-8]: {}", strerror(errno)); | 361 | LOG_ERROR(Common, "iconv failure [UTF-8]: {}", strerror(errno)); |
| 362 | break; | 362 | break; |
| 363 | } | 363 | } |
| 364 | } | 364 | } |