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 "Util.h"
23#include <algorithm>
24
25AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args) :
26 Appender(id, name, level, flags),
27 logfile(nullptr),
28 _logDir(sLog->GetLogsDir()),
29 _maxFileSize(0),
30 _fileSize(0)
31{
32 if (args.size() < 4)
33 throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender {}", name));
34
35 _fileName.assign(args[3]);
36
37 std::string mode = "a";
38 if (4 < args.size())
39 mode.assign(args[4]);
40
42 {
43 size_t dot_pos = _fileName.find_last_of('.');
44 if (dot_pos != std::string::npos)
45 _fileName.insert(dot_pos, sLog->GetLogsTimestamp());
46 else
47 _fileName += sLog->GetLogsTimestamp();
48 }
49
50 if (5 < args.size())
51 {
52 if (Optional<uint32> size = Trinity::StringTo<uint32>(args[5]))
53 _maxFileSize = *size;
54 else
55 throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid size '{}' for appender {}", args[5], name));
56 }
57
58 _dynamicName = std::string::npos != _fileName.find("%s");
60
61 if (!_dynamicName)
62 logfile = OpenFile(_fileName, mode, (mode == "w") && _backup);
63}
64
69
70void AppenderFile::_write(LogMessage const* message)
71{
72 bool exceedMaxSize = _maxFileSize > 0 && (_fileSize.load() + message->Size()) > _maxFileSize;
73
74 if (_dynamicName)
75 {
76 char namebuf[TRINITY_PATH_MAX];
77 snprintf(namebuf, TRINITY_PATH_MAX, _fileName.c_str(), message->param1.c_str());
78 // always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call
79 FILE* file = OpenFile(namebuf, "a", _backup || exceedMaxSize);
80 if (!file)
81 return;
82 fprintf(file, "%s%s\n", message->prefix.c_str(), message->text.c_str());
83 fflush(file);
84 _fileSize += uint64(message->Size());
85 fclose(file);
86 return;
87 }
88 else if (exceedMaxSize)
89 logfile = OpenFile(_fileName, "w", true);
90
91 if (!logfile)
92 return;
93
94 fprintf(logfile, "%s%s\n", message->prefix.c_str(), message->text.c_str());
95 fflush(logfile);
96 _fileSize += uint64(message->Size());
97}
98
99FILE* AppenderFile::OpenFile(std::string const& filename, std::string const& mode, bool backup)
100{
101 std::string fullName(_logDir + filename);
102 if (backup)
103 {
104 CloseFile();
105 std::string newName(fullName);
106 newName.push_back('.');
107 newName.append(LogMessage::getTimeStr(time(nullptr)));
108 std::replace(newName.begin(), newName.end(), ':', '-');
109 rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
110 }
111
112 if (FILE* ret = fopen(fullName.c_str(), mode.c_str()))
113 {
114 _fileSize = ftell(ret);
115 return ret;
116 }
117
118 return nullptr;
119}
120
122{
123 if (logfile)
124 {
125 fclose(logfile);
126 logfile = nullptr;
127 }
128}
uint8_t uint8
Definition Define.h:135
#define TRINITY_PATH_MAX
Definition Define.h:60
uint64_t uint64
Definition Define.h:132
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:130
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
std::atomic< uint64 > _fileSize
AppenderFile(uint8 id, std::string const &name, LogLevel level, AppenderFlags flags, std::vector< std::string_view > const &args)
uint64 _maxFileSize
void _write(LogMessage const *message) override
std::string _fileName
std::string _logDir
FILE * OpenFile(std::string const &name, std::string const &mode, bool backup)
std::string name
Definition Appender.h:50
AppenderFlags flags
Definition Appender.h:52
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
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