[PATCH] Log file limit and timestamp precision

Zoltán Dudás <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Organization SEI
Message-ID <[email protected]>
Hi All,

The Kannel has made me 2G log during a night and it stopped because of limits 
of filesystem. Of course it was abnormal operation and usually a Kannel log
file isn't so big. But I have modified the logging system of Kannel and it
won't happen again. If the size of a log file grows above 100Mb it renames
it and start writing into a new one. My another modification in the logging
system modify the time precision to milliseconds. I have too much log lines
with the same timestamp, I suppose it is very useful at bursts.

Zoli

--
Zoltan Dudas
Software Engineer
SEI Hungary
Office  +36-52-889-532 Ext: 2032
Fax     +36-52-889-599
Email   [email protected]
URL     www.sei-it.com
log.diff (text/x-diff, 4.9 KB)
? log.diff
Index: gwlib/log.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/log.c,v
retrieving revision 1.48
diff -u -r1.48 log.c
--- gwlib/log.c	8 Aug 2004 21:46:51 -0000	1.48
+++ gwlib/log.c	13 Oct 2004 09:34:26 -0000
@@ -107,6 +107,7 @@
     int minimum_output_level;
     char filename[FILENAME_MAX + 1]; /* to allow re-open */
     enum excl_state exclusive;
+	Mutex *mutex;
 } logfiles[MAX_LOGFILES];
 static int num_logfiles = 0;
 
@@ -160,6 +161,7 @@
     logfiles[num_logfiles].file = stderr;
     logfiles[num_logfiles].minimum_output_level = GW_DEBUG;
     logfiles[num_logfiles].exclusive = GW_NON_EXCL;
+	logfiles[num_logfiles].mutex= mutex_create();
     ++num_logfiles;
 }
 
@@ -244,7 +246,8 @@
     for (i = 0; i < num_logfiles; ++i) {
         if (logfiles[i].file != stderr) {
             found = 0;
-
+			
+			mutex_lock(logfiles[i].mutex);
             /*
              * Reverse seek for allready reopened logfile.
              * If we find a previous file descriptor for the same file
@@ -266,6 +269,7 @@
                 error(errno, "Couldn't re-open logfile `%s'.",
                       logfiles[i].filename);
             }
+			mutex_unlock(logfiles[i].mutex);
         }
     }
 
@@ -290,10 +294,12 @@
 
     while (num_logfiles > 0) {
         --num_logfiles;
+		mutex_lock(logfiles[num_logfiles].mutex);
         if (logfiles[num_logfiles].file != stderr &&
             logfiles[num_logfiles].file != NULL)
             fclose(logfiles[num_logfiles].file);
         logfiles[num_logfiles].file = NULL;
+		mutex_unlock(logfiles[num_logfiles].mutex);
     }
 
     /*
@@ -351,6 +357,7 @@
     logfiles[num_logfiles].file = f;
     logfiles[num_logfiles].minimum_output_level = level;
     logfiles[num_logfiles].exclusive = excl;
+	logfiles[num_logfiles].mutex= mutex_create();
     strcpy(logfiles[num_logfiles].filename, filename);
     ++num_logfiles;
     info(0, "Added logfile `%s' with level `%d'.", filename, level);
@@ -373,23 +380,23 @@
     };
     static int tab_size = sizeof(tab) / sizeof(tab[0]);
     time_t t;
+	struct timeval timeval;
     struct tm tm;
     char *p, prefix[1024];
     long tid, pid;
     
     p = prefix;
-
+ 
     if (with_timestamp) {
-        time(&t);
+	gettimeofday(&timeval,NULL);
 #if LOG_TIMESTAMP_LOCALTIME
-        tm = gw_localtime(t);
+	localtime_r((time_t*)&timeval.tv_sec,&tm);
 #else
-        tm = gw_gmtime(t);
+	gmtime_r((time_t*)&timeval.tv_sec,&tm);
 #endif
-        sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d ",
+        sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d.%04d ",
         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-        tm.tm_hour, tm.tm_min, tm.tm_sec);
-    
+        tm.tm_hour, tm.tm_min, tm.tm_sec, timeval.tv_usec/1000);
         p = strchr(p, '\0');
     }
 
@@ -464,6 +471,40 @@
     }
 }
 
+/* 
+ * Generate filename for log file
+ */
+char *log_gen_new_filename(const char *oldfilename)
+{
+	time_t t;
+	struct tm tm;
+	time(&t);
+	tm = gw_localtime(t);
+	char *new_filename= gw_malloc(FILENAME_MAX + 1);
+	snprintf(new_filename,FILENAME_MAX,"%s.%04d-%02d-%02d_%02d%02d%02d",
+		oldfilename,
+		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+		tm.tm_hour, tm.tm_min, tm.tm_sec);
+	return new_filename;
+}
+
+/*
+ * Exchange a too big log file to an empty one
+ */
+void log_exchange(int log_file_idx)
+{
+	FILE *lfile= logfiles[log_file_idx].file;
+	if (lfile != stderr && lseek(fileno(lfile),0,SEEK_CUR) > 100*1024*1024 /* 100M */) {
+		fclose(logfiles[log_file_idx].file);
+		char *new_filename= log_gen_new_filename(logfiles[log_file_idx].filename);
+		rename(logfiles[log_file_idx].filename,new_filename);
+		gw_free(new_filename);
+		logfiles[log_file_idx].file = fopen(logfiles[log_file_idx].filename, "a");
+		if (logfiles[log_file_idx].file == NULL) {
+			error(errno, "Couldn't re-open logfile `%s'.",logfiles[log_file_idx].filename);
+		}
+    }
+}	
 
 /*
  * Almost all of the message printing functions are identical, except for
@@ -490,9 +531,12 @@
 		if (logfiles[i].exclusive == GW_NON_EXCL && \
                     level >= logfiles[i].minimum_output_level && \
                     logfiles[i].file != NULL) { \
+				mutex_lock(logfiles[i].mutex); \
+				log_exchange(i); \
 		        va_start(args, fmt); \
 		        output(logfiles[i].file, buf, args); \
 		        va_end(args); \
+				mutex_unlock(logfiles[i].mutex); \
 		} \
 	    } \
             if (writers != NULL) \
@@ -519,9 +563,12 @@
             if (logfiles[e].exclusive == GW_EXCL && \
                 level >= logfiles[e].minimum_output_level && \
                 logfiles[e].file != NULL) { \
+				mutex_lock(logfiles[e].mutex); \
+				log_exchange(e); \
                 va_start(args, fmt); \
                 output(logfiles[e].file, buf, args); \
                 va_end(args); \
+				mutex_unlock(logfiles[e].mutex); \
             } \
             if (writers != NULL) \
               list_remove_producer(writers); \
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.