Browse Source

HPCC-21218 Add support for capping size of esp log files

Signed-off-by: Shamser Ahmed <shamser.ahmed@lexisnexis.com>
Shamser Ahmed 5 năm trước cách đây
mục cha
commit
99a5ca9822

+ 2 - 0
esp/platform/espp.cpp

@@ -291,9 +291,11 @@ void openEspLogFile(IPropertyTree* envpt, IPropertyTree* procpt)
     //logDir="-" is the default in application mode and logs to stderr, not to a file
     if (logdir.length() && !streq(logdir, "-"))
     {
+        long maxLogFileSize = procpt->getPropInt64("@maxLogFileSize", 0);
         Owned<IComponentLogFileCreator> lf = createComponentLogFileCreator(logdir.str(), "esp");
         lf->setName("esp_main");//override default filename
         lf->setAliasName("esp");
+        lf->setMaxLogFileSize(maxLogFileSize);
         lf->beginLogging();
     }
 #else

+ 3 - 0
initfiles/componentfiles/configschema/xsd/esp.xsd

@@ -328,6 +328,9 @@
                 <xs:attribute name="formOptionsAccess" type="xs:boolean" hpcc:presetValue="false"
                               hpcc:displayName="Form Options Access"
                               hpcc:tooltip="Allows show Options in test form page"/>
+                <xs:attribute name="maxLogFileSize" type="xs:nonNegativeInteger"
+                              hpcc:presetValue="0" hpcc:displayName="Max log file size"
+                              hpcc:tooltip="The maximum log file size (0 for no size limit)"/>
                 <xs:attribute name="maxRequestEntityLength" type="xs:nonNegativeInteger"
                               hpcc:presetValue="8000000" hpcc:displayName="Max Request Entity Length"
                               hpcc:tooltip="The maximum length of request entity allowed"/>

+ 7 - 0
initfiles/componentfiles/configxml/esp.xsd.in

@@ -924,6 +924,13 @@
                     </xs:appinfo>
                 </xs:annotation>
             </xs:attribute>
+            <xs:attribute name="maxLogFileSize" type="xs:nonNegativeInteger" use="optional" default="0">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <tooltip>The maximum log file size (0 for no size limit)</tooltip>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
             <xs:attribute name="maxRequestEntityLength" type="xs:nonNegativeInteger" use="optional" default="8000000">
                 <xs:annotation>
                     <xs:appinfo>

+ 1 - 0
initfiles/etc/DIR_NAME/environment.xml.in

@@ -264,6 +264,7 @@
               txSummaryResourceReq="false"
               maxBacklogQueueSize="200"
               maxConcurrentThreads="0"
+              maxLogFileSize="0"
               maxRequestEntityLength="8000000"
               minCompressLength="1000"
               name="myesp"

+ 35 - 8
system/jlib/jlog.cpp

@@ -1002,14 +1002,24 @@ void FileLogMsgHandlerXML::addToPTree(IPropertyTree * tree) const
 }
 
 // RollingFileLogMsgHandler
+#define MIN_LOGFILE_SIZE_LIMIT 10000
+#define LOG_LINE_SIZE_ESTIMATE 80
 
-RollingFileLogMsgHandler::RollingFileLogMsgHandler(const char * _filebase, const char * _fileextn, unsigned _fields, bool _append, bool _flushes, const char *initialName, const char *_alias, bool daily)
-  : handle(0), messageFields(_fields), alias(_alias), filebase(_filebase), fileextn(_fileextn), append(_append), flushes(_flushes)
+RollingFileLogMsgHandler::RollingFileLogMsgHandler(const char * _filebase, const char * _fileextn, unsigned _fields, bool _append, bool _flushes, const char *initialName, const char *_alias, bool daily, long _maxLogFileSize)
+  : handle(0), messageFields(_fields), alias(_alias), filebase(_filebase), fileextn(_fileextn), append(_append), flushes(_flushes), maxLogFileSize(_maxLogFileSize)
 {
+    if (_maxLogFileSize)
+    {
+        if (_maxLogFileSize < MIN_LOGFILE_SIZE_LIMIT)                 // Setting the cap too low, doesn't work well
+            maxLogFileSize = MIN_LOGFILE_SIZE_LIMIT;
+        maxLogFileSize = _maxLogFileSize - (LOG_LINE_SIZE_ESTIMATE*2); // Trying to keep log file size below capped
+    };
+
     time_t tNow;
     time(&tNow);
     localtime_r(&tNow, &startTime);
     doRollover(daily, initialName);
+    checkRollover();
 }
 
 RollingFileLogMsgHandler::~RollingFileLogMsgHandler()
@@ -1047,8 +1057,6 @@ void RollingFileLogMsgHandler::addToPTree(IPropertyTree * tree) const
     tree->addPropTree("handler", handlerTree);
 }
 
-#define ROLLOVER_PERIOD 86400
-
 void RollingFileLogMsgHandler::checkRollover()
 {
     time_t tNow;
@@ -1060,6 +1068,24 @@ void RollingFileLogMsgHandler::checkRollover()
         localtime_r(&tNow, &startTime);  // reset the start time for next rollover check
         doRollover(true);
     }
+    else if (maxLogFileSize)
+    {
+        linesSinceSizeChecked++;
+        if (linesSinceSizeChecked > sizeCheckNext)
+        {
+            long fsize = ftell(handle);
+            if ((fsize==-1 && errno==EOVERFLOW) || (fsize >= maxLogFileSize))
+            {
+                localtime_r(&tNow, &startTime);
+                doRollover(false);
+            }
+            else
+                // Calc how many lines to skip before next log file size check
+                //  - using (LOG_LINE_SIZE_ESTIMATE*2) to ensure the size check is done well before limit
+                sizeCheckNext = (maxLogFileSize - fsize) / (LOG_LINE_SIZE_ESTIMATE*2);
+            linesSinceSizeChecked = 0;
+        }
+    }
 }
 
 void RollingFileLogMsgHandler::doRollover(bool daily, const char *forceName)
@@ -2178,9 +2204,9 @@ ILogMsgHandler * getFileLogMsgHandler(const char * filename, const char * header
     return new FileLogMsgHandlerTable(filename, headertext, fields, append, flushes);
 }
 
-ILogMsgHandler * getRollingFileLogMsgHandler(const char * filebase, const char * fileextn, unsigned fields, bool append, bool flushes, const char *initialName, const char *alias, bool daily)
+ILogMsgHandler * getRollingFileLogMsgHandler(const char * filebase, const char * fileextn, unsigned fields, bool append, bool flushes, const char *initialName, const char *alias, bool daily, long maxLogSize)
 {
-    return new RollingFileLogMsgHandler(filebase, fileextn, fields, append, flushes, initialName, alias, daily);
+    return new RollingFileLogMsgHandler(filebase, fileextn, fields, append, flushes, initialName, alias, daily, maxLogSize);
 }
 
 ILogMsgHandler * getBinLogMsgHandler(const char * filename, bool append)
@@ -2867,6 +2893,7 @@ private:
     StringBuffer logDir;        //access via queryLogDir()
     StringBuffer aliasFileSpec; //access via queryAliasFileSpec()
     StringBuffer expandedLogSpec;//access via queryLogFileSpec()
+    long         maxLogFileSize = 0;
 
 private:
     void setDefaults()
@@ -2921,7 +2948,7 @@ public:
     void setAliasName(const char * _aliasName)   { aliasName.set(_aliasName); }
     void setLogDirSubdir(const char * _subdir)   { logDirSubdir.set(_subdir); }
     void setRolling(const bool _rolls)       { rolling = _rolls; }
-
+    void setMaxLogFileSize( const long _size)    { maxLogFileSize = _size; }
     //ILogMsgHandler fields
     void setAppend(const bool _append)       { append = _append; }
     void setFlushes(const bool _flushes)     { flushes = _flushes; }
@@ -2979,7 +3006,7 @@ public:
         ILogMsgHandler * lmh;
         if (rolling)
         {
-            lmh = getRollingFileLogMsgHandler(logFileSpec.str(), extension, msgFields, append, flushes, NULL, aliasFileSpec.str(), true);
+            lmh = getRollingFileLogMsgHandler(logFileSpec.str(), extension, msgFields, append, flushes, NULL, aliasFileSpec.str(), true, maxLogFileSize);
         }
         else
         {

+ 1 - 0
system/jlib/jlog.hpp

@@ -1213,6 +1213,7 @@ interface IComponentLogFileCreator : extends IInterface
     virtual void setAliasName(const char * _aliasName) = 0; //alias file name, overrides default of component name
     virtual void setLogDirSubdir(const char * _subdir) = 0; //subdir be appended to config log dir (eg "server" or "audit")
     virtual void setRolling(const bool _rolls) = 0;         //daily rollover to new file
+    virtual void setMaxLogFileSize(const long _size) = 0;   //maximum log file size (files too large rolled over)
     virtual void setCompleteFilespec(const char * _fs) = 0; //Full filespec (path/fn.ext), overrides everything else
 
     //ILogMsgHandler fields

+ 5 - 1
system/jlib/jlog.ipp

@@ -588,7 +588,8 @@ private:
 class RollingFileLogMsgHandler : implements ILogMsgHandler, public CInterface
 {
 public:
-    RollingFileLogMsgHandler(const char * _filebase, const char * _fileextn, unsigned _fields = MSGFIELD_all, bool _append = false, bool _flushes = true, const char *initialName = NULL, const char *alias = NULL, bool daily = false);
+    RollingFileLogMsgHandler(const char * _filebase, const char * _fileextn, unsigned _fields = MSGFIELD_all, bool _append = false, bool _flushes = true,
+                             const char *initialName = NULL, const char *alias = NULL, bool daily = false, long _maxLogFileSize = 0);
     virtual ~RollingFileLogMsgHandler();
     IMPLEMENT_IINTERFACE;
     void                      handleMessage(const LogMsg & msg)
@@ -633,6 +634,9 @@ protected:
     mutable CriticalSection   crit;
     mutable struct tm         startTime;
     bool printHeader = true;
+    long                      maxLogFileSize = 0;
+    long                      linesSinceSizeChecked = 0; // How many lines logged since last size check for rollover
+    long                      sizeCheckNext = 0;         // how many lines to skip before checking size again
 };
 
 // Implementation of handler which writes message to file in binary form