25#include <boost/format.hpp>
41 "Number of log files to keep before starting to delete old "
42 "files. If zero, no file will be deleted.");
44 "LogFileName",
"ArmarXLog",
"Logfilename without ending");
49 "If set, log will be stored in this path. If not set, log will be stored "
50 "in $ARMARX_USER_CONFIG_DIR/log/ (or $HOME/.armarx/log/ if $ARMARX_USER_CONFIG_DIR is "
54 "SplitByApplication",
true,
"Create additional log files for each application");
60 std::string directoryStr;
66 else if (
const char* workspace = std::getenv(
"ARMARX_USER_CONFIG_DIR"))
68 directoryStr = (std::filesystem::path(workspace) /
"log").
string();
72 directoryStr = std::string(
"$HOME/.armarx/log/");
78 if (!std::filesystem::exists(directory))
80 ARMARX_INFO <<
"Log path not found - creating it: " << directory.string();
81 std::error_code errcode;
82 std::filesystem::create_directories(directory, errcode);
85 ARMARX_ERROR <<
"Creating directories failed: " << errcode.message();
93 directoryStr,
getProperty<int>(
"MaxLogFileCount").getValue(), fileBasename, ending);
98 auto filePath = std::filesystem::path(filename);
99 directory /= filePath.stem();
100 if (!std::filesystem::exists(directory))
102 ARMARX_INFO <<
"Log path not found - creating it: " << directory;
103 std::error_code errcode;
104 std::filesystem::create_directories(directory, errcode);
107 ARMARX_ERROR <<
"Creating directories failed: " << errcode.message();
112 directory.string() +
"/" + filePath.stem().string() +
"-%1%." + ending;
116 auto logfilePath = std::filesystem::path(directoryStr) / std::filesystem::path(filename);
117 fileStream.open(logfilePath.string().c_str(), std::ofstream::out);
120 ARMARX_ERROR <<
"Failed to open " << logfilePath.string();
123 ARMARX_INFO <<
"Logging to " << logfilePath.string();
124 fileStream <<
"Log starting at " << IceUtil::Time::now().toDateTime() <<
", "
125 <<
"with log name " << filename <<
"\n";
137 std::unique_lock lock(
mutex);
155 std::vector<std::string>
158 std::vector<std::string> result;
159 namespace fs = std::filesystem;
160 fs::path someDir(dir);
161 fs::directory_iterator end_iter;
163 using result_set_t = std::multimap<std::filesystem::file_time_type, fs::path>;
164 result_set_t result_set;
166 if (fs::exists(someDir) && fs::is_directory(someDir))
168 for (fs::directory_iterator dir_iter(someDir); dir_iter != end_iter; ++dir_iter)
170 if (fs::is_regular_file(dir_iter->status()))
173 result_set_t::value_type(fs::last_write_time(dir_iter->path()), *dir_iter));
177 for (
auto it = result_set.rbegin(); it != result_set.rend(); ++it)
179 result.push_back(it->second.string());
187 const std::string& fileBasename,
188 const std::string& fileNameEnding)
const
192 std::string connectorString =
"-";
193 const boost::regex e(fileBasename + connectorString +
"([0-9]+)\\.");
195 int highestNumber = 0;
196 for (
auto file : files)
198 boost::match_results<std::string::const_iterator> what;
199 file = std::filesystem::path(file).filename().string();
201 bool found_match = boost::regex_search(file, what, e);
204 for (
size_t i = 1; i < what.size(); i += 2)
206 std::string numberStr = what[i];
207 int number = atoi(numberStr.c_str());
208 highestNumber = std::max(number, highestNumber);
210 auto filenameCandidate = fileBasename + connectorString +
212 if (std::filesystem::exists(dir +
"/" + filenameCandidate))
215 if (trials >= maxLogFileCount && maxLogFileCount > 0)
218 std::filesystem::remove(dir +
"/" + filenameCandidate);
226 return fileBasename + connectorString +
ValueToString(highestNumber) +
"." + fileNameEnding;
232 return "ArmarXFileLogger";
240 if (!msg.tag.empty())
242 catStr =
"[" + msg.tag +
"]: ";
248 IceUtil::Time time = IceUtil::Time::microSeconds(msg.time);
249 std::unique_lock lock(
mutex);
255 std::string logLevel;
258 case armarx::MessageType::eUNDEFINED:
259 logLevel =
"UNDEFINED";
261 case armarx::MessageType::eDEBUG:
264 case armarx::MessageType::eVERBOSE:
265 logLevel =
"VERBOSE";
267 case armarx::MessageType::eINFO:
270 case armarx::MessageType::eIMPORTANT:
271 logLevel =
"IMPORTANT";
273 case armarx::MessageType::eWARN:
276 case armarx::MessageType::eERROR:
279 case armarx::MessageType::eFATAL:
282 case armarx::MessageType::eLogLevelCount:
283 logLevel =
"LogLevelCount";
287 std::stringstream newLines;
288 newLines <<
"[" + time.toDateTime().substr(time.toDateTime().find(
' ') + 1) +
"]" +
"[" +
289 msg.who +
"]" + catStr +
"[" + logLevel +
"]";
290 newLines << msg.what <<
"\n";
300 std::shared_ptr<std::ofstream>(
301 new std::ofstream(filepath.str().c_str())))
304 if (!it->second->is_open())
306 ARMARX_WARNING <<
"Failed to open for logging: " << filepath.str();
311 *(it->second) << newLines.str();
static bool ReplaceEnvVars(std::string &string)
ReplaceEnvVars replaces environment variables in a string with their values, if the env.
ArmarXFileLoggerPropertyDefinitions(std::string prefix)
std::string applicationsLogFileBasePath
void onInitComponent() override
Pure virtual hook for the subclass.
std::vector< std::string > getDirListOrderedByDate(const std::string &dir) const
void onDisconnectComponent() override
Hook for subclass.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Creates the property definition container.
void onConnectComponent() override
Pure virtual hook for the subclass.
void writeLog(const LogMessage &, const Ice::Current &) override
std::map< std::string, std::shared_ptr< std::ofstream > > applicationFileStreams
std::string getNextLogFileNameAndDeleteOldFiles(const std::string &dir, int maxLogFileCount, const std::string &fileBasename, const std::string &fileNameEnding) const
void onExitComponent() override
Hook for subclass.
std::string getDefaultName() const override
Retrieve default name of component.
ComponentPropertyDefinitions(std::string prefix, bool hasObjectNameParameter=true)
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Property< PropertyType > getProperty(const std::string &name)
static std::string CropFunctionName(const std::string &originalFunctionName)
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
This file offers overloads of toIce() and fromIce() functions for STL container types.
fs::path remove_trailing_separator(fs::path p)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
std::string ValueToString(const T &value)