mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-05 03:37:28 +01:00
fixed log rotation issue
This commit is contained in:
parent
be8daabe3c
commit
b5b35cb173
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// FileChannel.h
|
// FileChannel.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Foundation/include/Poco/FileChannel.h#2 $
|
// $Id: //poco/1.3/Foundation/include/Poco/FileChannel.h#2 $
|
||||||
//
|
//
|
||||||
// Library: Foundation
|
// Library: Foundation
|
||||||
// Package: Logging
|
// Package: Logging
|
||||||
@ -87,6 +87,8 @@ class Foundation_API FileChannel: public Channel
|
|||||||
/// * daily: the file is rotated daily
|
/// * daily: the file is rotated daily
|
||||||
/// * weekly: the file is rotated every seven days
|
/// * weekly: the file is rotated every seven days
|
||||||
/// * monthly: the file is rotated every 30 days
|
/// * monthly: the file is rotated every 30 days
|
||||||
|
/// * <n> minutes: the file is rotated every <n> minutes,
|
||||||
|
/// where <n> is an integer greater than zero.
|
||||||
/// * <n> hours: the file is rotated every <n> hours, where
|
/// * <n> hours: the file is rotated every <n> hours, where
|
||||||
/// <n> is an integer greater than zero.
|
/// <n> is an integer greater than zero.
|
||||||
/// * <n> days: the file is rotated every <n> days, where
|
/// * <n> days: the file is rotated every <n> days, where
|
||||||
@ -103,6 +105,14 @@ class Foundation_API FileChannel: public Channel
|
|||||||
/// * <n> M: the file is rotated when its size exceeds
|
/// * <n> M: the file is rotated when its size exceeds
|
||||||
/// <n> Megabytes.
|
/// <n> Megabytes.
|
||||||
///
|
///
|
||||||
|
/// NOTE: For periodic log file rotation (daily, weekly, monthly, etc.),
|
||||||
|
/// the date and time of log file creation or last rotation is
|
||||||
|
/// written into the first line of the log file. This is because
|
||||||
|
/// there is no reliable way to find out the real creation date of
|
||||||
|
/// a file on many platforms (e.g., most Unix platforms do not
|
||||||
|
/// provide the creation date, and Windows has its own issues
|
||||||
|
/// with its "File System Tunneling Capabilities").
|
||||||
|
///
|
||||||
/// Using the "archive" property it is possible to specify
|
/// Using the "archive" property it is possible to specify
|
||||||
/// how archived log files are named. The following values
|
/// how archived log files are named. The following values
|
||||||
/// for the "archive" property are supported:
|
/// for the "archive" property are supported:
|
||||||
@ -151,15 +161,11 @@ class Foundation_API FileChannel: public Channel
|
|||||||
/// * <n> weeks: the maximum age is <n> weeks.
|
/// * <n> weeks: the maximum age is <n> weeks.
|
||||||
/// * <n> months: the maximum age is <n> months, where a month has 30 days.
|
/// * <n> months: the maximum age is <n> months, where a month has 30 days.
|
||||||
///
|
///
|
||||||
/// Both empty string ("") and n == 0 indicate no purging.
|
|
||||||
///
|
|
||||||
/// The purgeCount property has an integer value that
|
/// The purgeCount property has an integer value that
|
||||||
/// specifies the maximum number of archived log files.
|
/// specifies the maximum number of archived log files.
|
||||||
/// If the number is exceeded, archived log files are
|
/// If the number is exceeded, archived log files are
|
||||||
/// deleted, starting with the oldest.
|
/// deleted, starting with the oldest.
|
||||||
///
|
///
|
||||||
/// Both empty string ("") and "0" for indicate no purging.
|
|
||||||
///
|
|
||||||
/// For a more lightweight file channel class, see SimpleFileChannel.
|
/// For a more lightweight file channel class, see SimpleFileChannel.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// RotateStrategy.h
|
// RotateStrategy.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Foundation/include/Poco/RotateStrategy.h#2 $
|
// $Id: //poco/1.3/Foundation/include/Poco/RotateStrategy.h#3 $
|
||||||
//
|
//
|
||||||
// Library: Foundation
|
// Library: Foundation
|
||||||
// Package: Logging
|
// Package: Logging
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mustRotate(LogFile* pFile = 0)
|
bool mustRotate(LogFile* pFile)
|
||||||
{
|
{
|
||||||
if (DT() >= _threshold)
|
if (DT() >= _threshold)
|
||||||
{
|
{
|
||||||
@ -149,6 +149,11 @@ private:
|
|||||||
class Foundation_API RotateByIntervalStrategy: public RotateStrategy
|
class Foundation_API RotateByIntervalStrategy: public RotateStrategy
|
||||||
/// The file is rotated when the log file
|
/// The file is rotated when the log file
|
||||||
/// exceeds a given age.
|
/// exceeds a given age.
|
||||||
|
///
|
||||||
|
/// For this to work reliably across all platforms and file systems
|
||||||
|
/// (there are severe issues on most platforms finding out the real
|
||||||
|
/// creation date of a file), the creation date of the file is
|
||||||
|
/// written into the log file as the first entry.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RotateByIntervalStrategy(const Timespan& span);
|
RotateByIntervalStrategy(const Timespan& span);
|
||||||
@ -157,6 +162,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Timespan _span;
|
Timespan _span;
|
||||||
|
Timestamp _lastRotate;
|
||||||
|
static const std::string ROTATE_TEXT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Unicode.h
|
// Unicode.h
|
||||||
//
|
//
|
||||||
// $Id: //poco/1.3/Foundation/include/Poco/Unicode.h#1 $
|
// $Id: //poco/1.3/Foundation/include/Poco/Unicode.h#2 $
|
||||||
//
|
//
|
||||||
// Library: Foundation
|
// Library: Foundation
|
||||||
// Package: Text
|
// Package: Text
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// FileChannel.cpp
|
// FileChannel.cpp
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Foundation/src/FileChannel.cpp#2 $
|
// $Id: //poco/1.3/Foundation/src/FileChannel.cpp#3 $
|
||||||
//
|
//
|
||||||
// Library: Foundation
|
// Library: Foundation
|
||||||
// Package: Logging
|
// Package: Logging
|
||||||
@ -130,6 +130,10 @@ void FileChannel::log(const Message& msg)
|
|||||||
{
|
{
|
||||||
_pFile = new LogFile(_path);
|
_pFile = new LogFile(_path);
|
||||||
}
|
}
|
||||||
|
// we must call mustRotate() again to give the
|
||||||
|
// RotateByIntervalStrategy a chance to write its timestamp
|
||||||
|
// to the new file.
|
||||||
|
_pRotateStrategy->mustRotate(_pFile);
|
||||||
}
|
}
|
||||||
_pFile->write(msg.getText());
|
_pFile->write(msg.getText());
|
||||||
}
|
}
|
||||||
@ -240,6 +244,8 @@ void FileChannel::setRotation(const std::string& rotation)
|
|||||||
pStrategy = new RotateByIntervalStrategy(Timespan(30*Timespan::DAYS));
|
pStrategy = new RotateByIntervalStrategy(Timespan(30*Timespan::DAYS));
|
||||||
else if (unit == "seconds") // for testing only
|
else if (unit == "seconds") // for testing only
|
||||||
pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::SECONDS));
|
pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::SECONDS));
|
||||||
|
else if (unit == "minutes")
|
||||||
|
pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::MINUTES));
|
||||||
else if (unit == "hours")
|
else if (unit == "hours")
|
||||||
pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::HOURS));
|
pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::HOURS));
|
||||||
else if (unit == "days")
|
else if (unit == "days")
|
||||||
@ -296,14 +302,6 @@ void FileChannel::setCompress(const std::string& compress)
|
|||||||
|
|
||||||
void FileChannel::setPurgeAge(const std::string& age)
|
void FileChannel::setPurgeAge(const std::string& age)
|
||||||
{
|
{
|
||||||
if (age.empty())
|
|
||||||
{
|
|
||||||
delete _pPurgeStrategy;
|
|
||||||
_pPurgeStrategy = 0;
|
|
||||||
_purgeAge.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string::const_iterator it = age.begin();
|
std::string::const_iterator it = age.begin();
|
||||||
std::string::const_iterator end = age.end();
|
std::string::const_iterator end = age.end();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@ -328,12 +326,7 @@ void FileChannel::setPurgeAge(const std::string& age)
|
|||||||
throw InvalidArgumentException("purgeAge", age);
|
throw InvalidArgumentException("purgeAge", age);
|
||||||
|
|
||||||
delete _pPurgeStrategy;
|
delete _pPurgeStrategy;
|
||||||
|
|
||||||
if (0 == n || age.empty())
|
|
||||||
_pPurgeStrategy = 0;
|
|
||||||
else
|
|
||||||
_pPurgeStrategy = new PurgeByAgeStrategy(Timespan(factor*n));
|
_pPurgeStrategy = new PurgeByAgeStrategy(Timespan(factor*n));
|
||||||
|
|
||||||
_purgeAge = age;
|
_purgeAge = age;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,12 +341,7 @@ void FileChannel::setPurgeCount(const std::string& count)
|
|||||||
while (it != end && std::isspace(*it)) ++it;
|
while (it != end && std::isspace(*it)) ++it;
|
||||||
|
|
||||||
delete _pPurgeStrategy;
|
delete _pPurgeStrategy;
|
||||||
|
|
||||||
if (0 == n || count.empty())
|
|
||||||
_pPurgeStrategy = 0;
|
|
||||||
else
|
|
||||||
_pPurgeStrategy = new PurgeByCountStrategy(n);
|
_pPurgeStrategy = new PurgeByCountStrategy(n);
|
||||||
|
|
||||||
_purgeCount = count;
|
_purgeCount = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// RotateStrategy.cpp
|
// RotateStrategy.cpp
|
||||||
//
|
//
|
||||||
// $Id: //poco/svn/Foundation/src/RotateStrategy.cpp#2 $
|
// $Id: //poco/1.3/Foundation/src/RotateStrategy.cpp#2 $
|
||||||
//
|
//
|
||||||
// Library: Foundation
|
// Library: Foundation
|
||||||
// Package: Logging
|
// Package: Logging
|
||||||
@ -35,6 +35,10 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/RotateStrategy.h"
|
#include "Poco/RotateStrategy.h"
|
||||||
|
#include "Poco/FileStream.h"
|
||||||
|
#include "Poco/DateTimeParser.h"
|
||||||
|
#include "Poco/DateTimeFormatter.h"
|
||||||
|
#include "Poco/DateTimeFormat.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -60,7 +64,12 @@ RotateStrategy::~RotateStrategy()
|
|||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
RotateByIntervalStrategy::RotateByIntervalStrategy(const Timespan& span): _span(span)
|
const std::string RotateByIntervalStrategy::ROTATE_TEXT("# Log file created/rotated ");
|
||||||
|
|
||||||
|
|
||||||
|
RotateByIntervalStrategy::RotateByIntervalStrategy(const Timespan& span):
|
||||||
|
_span(span),
|
||||||
|
_lastRotate(0)
|
||||||
{
|
{
|
||||||
if (span.totalMicroseconds() <= 0) throw InvalidArgumentException("time span must be greater than zero");
|
if (span.totalMicroseconds() <= 0) throw InvalidArgumentException("time span must be greater than zero");
|
||||||
}
|
}
|
||||||
@ -73,8 +82,31 @@ RotateByIntervalStrategy::~RotateByIntervalStrategy()
|
|||||||
|
|
||||||
bool RotateByIntervalStrategy::mustRotate(LogFile* pFile)
|
bool RotateByIntervalStrategy::mustRotate(LogFile* pFile)
|
||||||
{
|
{
|
||||||
|
if (_lastRotate == 0 || pFile->size() == 0)
|
||||||
|
{
|
||||||
|
if (pFile->size() != 0)
|
||||||
|
{
|
||||||
|
Poco::FileInputStream istr(pFile->path());
|
||||||
|
std::string tag;
|
||||||
|
std::getline(istr, tag);
|
||||||
|
if (tag.compare(0, ROTATE_TEXT.size(), ROTATE_TEXT) == 0)
|
||||||
|
{
|
||||||
|
std::string timestamp(tag, ROTATE_TEXT.size());
|
||||||
|
int tzd;
|
||||||
|
_lastRotate = DateTimeParser::parse(DateTimeFormat::RFC1036_FORMAT, timestamp, tzd).timestamp();
|
||||||
|
}
|
||||||
|
else _lastRotate = pFile->creationDate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lastRotate.update();
|
||||||
|
std::string tag(ROTATE_TEXT);
|
||||||
|
tag += DateTimeFormatter::format(_lastRotate, DateTimeFormat::RFC1036_FORMAT);
|
||||||
|
pFile->write(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
Timestamp now;
|
Timestamp now;
|
||||||
return _span <= now - pFile->creationDate();
|
return _span <= now - _lastRotate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user