TrinityCore
Loading...
Searching...
No Matches
AppenderFile.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "AppenderFile.h"
19#include "Log.h"
20#include "LogMessage.h"
21#include "StringConvert.h"
22#include <algorithm>
23
24AppenderFile::AppenderFile(uint8 id, std::string name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args) :
25 Appender(id, std::move(name), level, flags),
26 logfile(nullptr),
27 _logDir(sLog->GetLogsDir()),
28 _maxFileSize(0),
29 _fileSize(0)
30{
31 if (args.size() < 4)
32 throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender {}", name));
33
34 _fileName.assign(args[3]);
35
36 std::string mode = "a";
37 if (4 < args.size())
38 mode.assign(args[4]);
39
41 {
42 size_t dot_pos = _fileName.find_last_of('.');
43 if (dot_pos != std::string::npos)
44 _fileName.insert(dot_pos, sLog->GetLogsTimestamp());
45 else
46 _fileName += sLog->GetLogsTimestamp();
47 }
48
49 if (5 < args.size())
50 {
51 if (Optional<uint32> size = Trinity::StringTo<uint32>(args[5]))
52 _maxFileSize = *size;
53 else
54 throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid size '{}' for appender {}", args[5], name));
55 }
56
57 _dynamicName = std::string::npos != _fileName.find("%s");
59
60 if (!_dynamicName)
61 logfile = OpenFile(_fileName, mode, (mode == "w") && _backup);
62}
63
68
69void AppenderFile::_write(LogMessage const* message)
70{
71 bool exceedMaxSize = _maxFileSize > 0 && (_fileSize.load() + message->Size()) > _maxFileSize;
72
73 if (_dynamicName)
74 {
75 char namebuf[TRINITY_PATH_MAX];
76 snprintf(namebuf, TRINITY_PATH_MAX, _fileName.c_str(), message->param1.c_str());
77 // always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call
78 FILE* file = OpenFile(namebuf, "a", _backup || exceedMaxSize);
79 if (!file)
80 return;
81 fwrite(message->prefix.c_str(), 1, message->prefix.length(), file);
82 fwrite(message->text.c_str(), 1, message->text.length(), file);
83 fwrite("\n", 1, 1, file);
84 fflush(file);
85 _fileSize += uint64(message->Size());
86 fclose(file);
87 return;
88 }
89 else if (exceedMaxSize)
90 logfile = OpenFile(_fileName, "w", true);
91
92 if (!logfile)
93 return;
94
95 fwrite(message->prefix.c_str(), 1, message->prefix.length(), logfile);
96 fwrite(message->text.c_str(), 1, message->text.length(), logfile);
97 fwrite("\n", 1, 1, logfile);
98 fflush(logfile);
99 _fileSize += uint64(message->Size());
100}
101
102FILE* AppenderFile::OpenFile(std::string const& filename, std::string const& mode, bool backup)
103{
104 std::string fullName(_logDir + filename);
105 if (backup)
106 {
107 CloseFile();
108 std::string newName(fullName);
109 newName.push_back('.');
110 newName.append(LogMessage::getTimeStr(time(nullptr)));
111 std::replace(newName.begin(), newName.end(), ':', '-');
112 rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
113 }
114
115 if (FILE* ret = fopen(fullName.c_str(), mode.c_str()))
116 {
117 _fileSize = ftell(ret);
118 return ret;
119 }
120
121 return nullptr;
122}
123
125{
126 if (logfile)
127 {
128 fclose(logfile);
129 logfile = nullptr;
130 }
131}
uint8_t uint8
Definition Define.h:156
#define TRINITY_PATH_MAX
Definition Define.h:63
uint64_t uint64
Definition Define.h:153
uint16 flags
AppenderFlags
Definition LogCommon.h:50
@ APPENDER_FLAGS_MAKE_FILE_BACKUP
Definition LogCommon.h:56
@ APPENDER_FLAGS_USE_TIMESTAMP
Definition LogCommon.h:55
LogLevel
Definition LogCommon.h:25
#define sLog
Definition Log.h:156
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
std::atomic< uint64 > _fileSize
uint64 _maxFileSize
void _write(LogMessage const *message) override
std::string _fileName
AppenderFile(uint8 id, std::string name, LogLevel level, AppenderFlags flags, std::vector< std::string_view > const &args)
std::string _logDir
FILE * OpenFile(std::string const &name, std::string const &mode, bool backup)
std::string name
Definition Appender.h:54
AppenderFlags flags
Definition Appender.h:56
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
STL namespace.
std::string const text
Definition LogMessage.h:39
std::string getTimeStr() const
uint32 Size() const
@ Returns size of the log message content in bytes
Definition LogMessage.h:45
std::string param1
Definition LogMessage.h:41
std::string prefix
Definition LogMessage.h:40