]> git.pld-linux.org Git - packages/syslog-ng.git/blob - log-file-size-limit.patch
9cedc104dbfd7f971ce85dacbf28ddb44ea6fdbf
[packages/syslog-ng.git] / log-file-size-limit.patch
1
2 https://lists.balabit.hu/pipermail/syslog-ng/2009-August/013325.html
3
4  
5     [syslog-ng] PATCH: Log file size limit (was: Logfile Rotation)
6
7 Balazs Scheidler wrote:
8 >> 
9 >> Personally I prefer to arrange log rotation based on the file size 
10 >> rather than some fixed time interval, so I have added that feature 
11 >> to syslog-ng. If anyone is interested I can explain in more details
12 >>  and post the patch.
13
14 > Please do. That's what open source is about.
15
16
17 The following patch introduces two new configuration options:
18 'file_size_limit' to be used inside global 'options' and 'size_limit' to
19 be used inside 'file' destination. Each option specifies log file size
20 limit in bytes. If the global option is set to a value greater than zero
21 it applies to all 'file' destinations. A particular file destination can
22 remove the limit by setting it to zero. For example:
23
24 # set the global file size limit
25 options { file_size_limit(123456); };
26
27 # set a different size limit for a particular file destination
28 destination log1 { file("/var/log/log1.log" size_limit(456789)); };
29
30 # remove size limit for a particular file destination
31 # (only useful if there is a global size limit set)
32 destination log2 { file("/var/log/log2.log" size_limit(0)); };
33
34 The file size is checked after writing each log message and if the file
35 has grown up to or above the size limit the file is renamed and a new
36 empty file is created to continue logging to. The name format the
37 "overgrown" log file is renamed to is "<p>-<s>.<m>-<r>", where <p> - the
38 full path and name of the original log file, <s> - current time in UNIX
39 format (seconds since Jan 1, 1970), <m> - fractional part of the current
40 time (microseconds, 6 digits), <r> - a random number (10 digits).
41
42 The intended use is to have incrond or another similar mechanism to
43 detect when there is a new "renamed" log file and to process it in
44 whatever way necessary (gzip it, parse it, send it my email, etc.).
45
46 *********** BEGIN PATCH ***********
47 diff -U5 -rb syslog-ng-3.0.4-orig/src/affile.c syslog-ng-3.0.4/src/affile.c
48 --- syslog-ng-3.0.4-orig/src/affile.c   2009-07-31 11:41:20.000000000 +0200
49 +++ syslog-ng-3.0.4/src/affile.c        2009-08-17 11:02:41.000000000 +0200
50 @@ -428,14 +428,72 @@
51  {
52    return log_queue_get_length(((LogWriter *) self->writer)->queue) == 0;
53  }
54  
55  static gboolean
56 +affile_dw_open_file(AFFileDestWriter *self, int *fd)
57 +{
58 +  return affile_open_file(self->filename->str, (self->owner->flags & AFFILE_PIPE)?
59 +                            (O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE):
60 +                            (O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK | O_LARGEFILE),
61 +                          self->owner->file_uid, self->owner->file_gid, self->owner->file_perm,
62 +                          self->owner->dir_uid, self->owner->dir_gid, self->owner->dir_perm,
63 +                          !!(self->owner->flags & AFFILE_CREATE_DIRS), FALSE, !!(self->owner->flags & AFFILE_PIPE), fd);
64 +}
65 +
66 +static void
67 +affile_dw_transport_callback(gint fd, void *context)
68 +{
69 +  static const size_t extra_length = 32;
70 +  AFFileDestWriter *self = (AFFileDestWriter *) context;
71 +  off_t size = lseek(fd, 0, SEEK_CUR);
72 +  GTimeVal time;
73 +  GString *name;
74 +  int reopen_fd;
75 +  if ((size > 0) && (size >= self->owner->size_limit))
76 +    {
77 +      /* TODO: use g_file_read_link() */
78 +      g_get_current_time(&time);
79 +      name = g_string_sized_new(self->filename->len + extra_length);
80 +      g_string_printf(name, "%s-%lu.%06lu-%010lu", self->filename->str, (gulong)time.tv_sec, (gulong)time.tv_usec, (gulong)g_random_int());
81 +      if (rename(self->filename->str, name->str) == 0)
82 +        {
83 +          if (affile_dw_open_file(self, &reopen_fd))
84 +            {
85 +              if (dup2(reopen_fd, fd) < 0)
86 +                {
87 +                  msg_error("Error swithing to new log file",
88 +                            evt_tag_str("filename", self->filename->str),
89 +                            evt_tag_errno(EVT_TAG_OSERROR, errno),
90 +                            NULL);
91 +                }
92 +              close(reopen_fd);
93 +            }
94 +          else
95 +            {
96 +              msg_error("Error opening file for writing",
97 +                        evt_tag_str("filename", self->filename->str),
98 +                        evt_tag_errno(EVT_TAG_OSERROR, errno),
99 +                        NULL);
100 +            }
101 +        }
102 +      else
103 +        {
104 +          msg_error("Error renaming overgrown file",
105 +                    evt_tag_str("filename", self->filename->str),
106 +                    evt_tag_errno(EVT_TAG_OSERROR, errno),
107 +                    NULL);
108 +        }
109 +      g_string_free(name, TRUE);
110 +    }
111 +}
112 +
113 +static gboolean
114  affile_dw_init(LogPipe *s)
115  {
116    AFFileDestWriter *self = (AFFileDestWriter *) s;
117 -  int fd, flags;
118 +  int fd;
119    struct stat st;
120    GlobalConfig *cfg = log_pipe_get_config(s);
121  
122    if (cfg)
123      self->time_reopen = cfg->time_reopen;
124 @@ -454,20 +512,12 @@
125                   evt_tag_int("overwrite_if_older", self->owner->overwrite_if_older),
126                   NULL);
127        unlink(self->filename->str);
128      }
129  
130 -  if (self->owner->flags & AFFILE_PIPE)
131 -    flags = O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
132 -  else
133 -    flags = O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
134 -
135    self->last_open_stamp = time(NULL);
136 -  if (affile_open_file(self->filename->str, flags, 
137 -                       self->owner->file_uid, self->owner->file_gid, self->owner->file_perm, 
138 -                       self->owner->dir_uid, self->owner->dir_gid, self->owner->dir_perm, 
139 -                       !!(self->owner->flags & AFFILE_CREATE_DIRS), FALSE, !!(self->owner->flags & AFFILE_PIPE), &fd))
140 +  if (affile_dw_open_file(self, &fd))
141      {
142        guint write_flags;
143        
144        if (!self->writer)
145          {
146 @@ -482,11 +532,11 @@
147            self->writer = NULL;
148            close(fd);
149            return FALSE;
150          }
151        write_flags = ((self->owner->flags & AFFILE_FSYNC) ? LTF_FSYNC : 0) | LTF_APPEND;
152 -      log_writer_reopen(self->writer, log_proto_plain_new_client(log_transport_plain_new(fd, write_flags)));
153 +      log_writer_reopen(self->writer, log_proto_plain_new_client(((self->owner->size_limit > 0) && !(self->owner->flags & AFFILE_PIPE))? log_transport_plain_new_with_callback(fd, write_flags, affile_dw_transport_callback, self): log_transport_plain_new(fd, write_flags)));
154      }
155    else
156      {
157        msg_error("Error opening file for writing",
158                  evt_tag_str("filename", self->filename->str),
159 @@ -678,10 +728,18 @@
160    AFFileDestDriver *self = (AFFileDestDriver *) s;
161  
162    self->local_time_zone = g_strdup(local_time_zone);
163  }
164  
165 +void
166 +affile_dd_set_file_size_limit(LogDriver *s, off_t file_size_limit)
167 +{
168 +  AFFileDestDriver *self = (AFFileDestDriver *) s;
169 +
170 +  self->size_limit = file_size_limit;
171 +}
172 +
173  static inline gchar *
174  affile_dd_format_persist_name(AFFileDestDriver *self)
175  {
176    static gchar persist_name[1024];
177  
178 @@ -766,10 +824,12 @@
179      self->dir_gid = cfg->dir_gid;
180    if (self->dir_perm == (mode_t) -1)
181      self->dir_perm = cfg->dir_perm;
182    if (self->time_reap == -1)
183      self->time_reap = cfg->time_reap;
184 +  if (self->size_limit == -1)
185 +    self->size_limit = cfg->file_size_limit;
186    
187    self->use_time_recvd = cfg->use_time_recvd;
188  
189    if (self->local_time_zone_info)
190      time_zone_info_free(self->local_time_zone_info);
191 @@ -973,7 +1033,8 @@
192    if (strchr(filename, '$') == NULL)
193      {
194        self->flags |= AFFILE_NO_EXPAND;
195      }
196    self->time_reap = -1;
197 +  self->size_limit = -1;
198    return &self->super;
199  }
200 diff -U5 -rb syslog-ng-3.0.4-orig/src/affile.h syslog-ng-3.0.4/src/affile.h
201 --- syslog-ng-3.0.4-orig/src/affile.h   2009-04-30 12:22:53.000000000 +0200
202 +++ syslog-ng-3.0.4/src/affile.h        2009-08-17 10:10:39.000000000 +0200
203 @@ -72,10 +72,11 @@
204      
205    gint overwrite_if_older;
206    gboolean use_time_recvd;
207    gint time_reap;
208    guint reap_timer;
209 +  off_t size_limit;
210  } AFFileDestDriver;
211  
212  LogDriver *affile_dd_new(gchar *filename, guint32 flags);
213  
214  void affile_dd_set_compress(LogDriver *s, gboolean compress);
215 @@ -88,7 +89,8 @@
216  void affile_dd_set_dir_perm(LogDriver *s, mode_t dir_perm);
217  void affile_dd_set_create_dirs(LogDriver *s, gboolean create_dirs);
218  void affile_dd_set_fsync(LogDriver *s, gboolean enable);
219  void affile_dd_set_overwrite_if_older(LogDriver *s, gint overwrite_if_older);
220  void affile_dd_set_local_time_zone(LogDriver *s, const gchar *local_time_zone);
221 +void affile_dd_set_file_size_limit(LogDriver *s, off_t file_size_limit);
222  
223  #endif
224 diff -U5 -rb syslog-ng-3.0.4-orig/src/cfg-grammar.y syslog-ng-3.0.4/src/cfg-grammar.y
225 --- syslog-ng-3.0.4-orig/src/cfg-grammar.y      2009-08-05 12:34:18.000000000 +0200
226 +++ syslog-ng-3.0.4/src/cfg-grammar.y   2009-08-17 10:10:39.000000000 +0200
227 @@ -154,10 +154,11 @@
228  %token KW_DIR_OWNER KW_DIR_GROUP KW_DIR_PERM 
229  %token KW_TEMPLATE KW_TEMPLATE_ESCAPE
230  %token KW_FOLLOW_FREQ
231  %token KW_OVERWRITE_IF_OLDER
232  %token KW_DEFAULT_FACILITY KW_DEFAULT_LEVEL
233 +%token KW_FILE_SIZE_LIMIT KW_SIZE_LIMIT
234  
235  /* socket related options */
236  %token KW_KEEP_ALIVE KW_MAX_CONNECTIONS
237  %token KW_LOCALIP KW_IP KW_LOCALPORT KW_PORT KW_DESTPORT
238  %token KW_IP_TTL KW_SO_BROADCAST KW_IP_TOS KW_SO_SNDBUF KW_SO_RCVBUF KW_SO_KEEPALIVE KW_SPOOF_SOURCE
239 @@ -799,10 +800,11 @@
240         | KW_DIR_PERM '(' LL_NUMBER ')'         { affile_dd_set_dir_perm(last_driver, $3); }
241         | KW_CREATE_DIRS '(' yesno ')'          { affile_dd_set_create_dirs(last_driver, $3); }
242         | KW_OVERWRITE_IF_OLDER '(' LL_NUMBER ')'       { affile_dd_set_overwrite_if_older(last_driver, $3); }
243         | KW_FSYNC '(' yesno ')'                { affile_dd_set_fsync(last_driver, $3); }
244         | KW_LOCAL_TIME_ZONE '(' string ')'     { affile_dd_set_local_time_zone(last_driver, $3); free($3); }
245 +       | KW_SIZE_LIMIT '(' LL_NUMBER ')'       { affile_dd_set_file_size_limit(last_driver, $3); }
246         ;
247  
248  dest_afpipe
249         : KW_PIPE '(' dest_afpipe_params ')'    { $$ = $3; }
250         ;
251 @@ -1141,10 +1143,11 @@
252         | KW_FILE_TEMPLATE '(' string ')'       { configuration->file_template_name = g_strdup($3); free($3); }
253         | KW_PROTO_TEMPLATE '(' string ')'      { configuration->proto_template_name = g_strdup($3); free($3); }
254         | KW_RECV_TIME_ZONE '(' string ')'      { configuration->recv_time_zone = g_strdup($3); free($3); }
255         | KW_SEND_TIME_ZONE '(' string ')'      { configuration->send_time_zone = g_strdup($3); free($3); }
256         | KW_LOCAL_TIME_ZONE '(' string ')'     { configuration->local_time_zone = g_strdup($3); free($3); }
257 +       | KW_FILE_SIZE_LIMIT '(' LL_NUMBER ')'  { configuration->file_size_limit = $3; }
258         ;
259  
260  /* BEGIN MARK: tls */
261  tls_options
262         : tls_option tls_options
263 diff -U5 -rb syslog-ng-3.0.4-orig/src/cfg-lex.l syslog-ng-3.0.4/src/cfg-lex.l
264 --- syslog-ng-3.0.4-orig/src/cfg-lex.l  2009-05-06 11:20:22.000000000 +0200
265 +++ syslog-ng-3.0.4/src/cfg-lex.l       2009-08-17 10:10:39.000000000 +0200
266 @@ -126,10 +126,12 @@
267          { "recv_time_zone",    KW_RECV_TIME_ZONE },
268          { "send_time_zone",    KW_SEND_TIME_ZONE },
269          { "local_time_zone",    KW_LOCAL_TIME_ZONE },
270          { "use_time_recvd",    KW_USE_TIME_RECVD, KWS_OBSOLETE, "Use R_ or S_ prefixed macros in templates" },
271          { "use_fqdn",           KW_USE_FQDN },
272 +        { "size_limit",        KW_SIZE_LIMIT },
273 +        { "file_size_limit",   KW_FILE_SIZE_LIMIT },
274         { "use_dns",            KW_USE_DNS },
275         { "gc_threshold",       KW_GC_BUSY_THRESHOLD },
276         { "gc_busy_threshold",  KW_GC_BUSY_THRESHOLD },
277         { "gc_idle_threshold",  KW_GC_IDLE_THRESHOLD },
278         { "time_reopen",        KW_TIME_REOPEN },
279 diff -U5 -rb syslog-ng-3.0.4-orig/src/cfg.c syslog-ng-3.0.4/src/cfg.c
280 --- syslog-ng-3.0.4-orig/src/cfg.c      2009-04-30 12:00:54.000000000 +0200
281 +++ syslog-ng-3.0.4/src/cfg.c   2009-08-17 10:10:39.000000000 +0200
282 @@ -298,10 +298,11 @@
283  
284    self->follow_freq = -1;
285    self->file_uid = 0;
286    self->file_gid = 0;
287    self->file_perm = 0600;
288 +  self->file_size_limit = 0;
289    self->dir_uid = 0;
290    self->dir_gid = 0;
291    self->dir_perm = 0700;
292  
293    self->use_dns_cache = 1;
294 diff -U5 -rb syslog-ng-3.0.4-orig/src/cfg.h syslog-ng-3.0.4/src/cfg.h
295 --- syslog-ng-3.0.4-orig/src/cfg.h      2009-06-03 13:08:27.000000000 +0200
296 +++ syslog-ng-3.0.4/src/cfg.h   2009-08-17 10:10:39.000000000 +0200
297 @@ -78,10 +78,11 @@
298    gint follow_freq;
299    gboolean create_dirs;
300    uid_t file_uid;
301    gid_t file_gid;
302    mode_t file_perm;
303 +  off_t file_size_limit;
304    
305    uid_t dir_uid;
306    gid_t dir_gid;
307    mode_t dir_perm;
308  
309 diff -U5 -rb syslog-ng-3.0.4-orig/src/logtransport.c syslog-ng-3.0.4/src/logtransport.c
310 --- syslog-ng-3.0.4-orig/src/logtransport.c     2009-04-30 10:53:22.000000000 +0200
311 +++ syslog-ng-3.0.4/src/logtransport.c  2009-08-17 11:01:33.000000000 +0200
312 @@ -53,10 +53,12 @@
313  typedef struct _LogTransportPlain LogTransportPlain;
314  
315  struct _LogTransportPlain
316  {
317    LogTransport super;
318 +  LogTransportCallback callback;
319 +  void *context;
320  };
321  
322  static gssize
323  log_transport_plain_read_method(LogTransport *s, gpointer buf, gsize buflen, GSockAddr **sa)
324  {
325 @@ -138,24 +140,32 @@
326          alarm_cancel();
327        if (self->super.flags & LTF_FSYNC)
328          fsync(self->super.fd);
329      }
330    while (rc == -1 && errno == EINTR);
331 +  if ((self->callback != NULL) && (rc > 0))
332 +    self->callback(self->super.fd, self->context);
333    return rc;
334  }
335  
336  
337  LogTransport *
338 -log_transport_plain_new(gint fd, guint flags)
339 +log_transport_plain_new_with_callback(gint fd, guint flags, LogTransportCallback callback, void *context)
340  {
341    LogTransportPlain *self = g_new0(LogTransportPlain, 1);
342    
343    self->super.fd = fd;
344    self->super.cond = 0;
345    self->super.flags = flags;
346    self->super.read = log_transport_plain_read_method;
347    self->super.write = log_transport_plain_write_method;
348    self->super.free_fn = log_transport_free_method;
349 +  self->callback = callback;
350 +  self->context = context;
351    return &self->super;
352  }
353  
354 -
355 +LogTransport *
356 +log_transport_plain_new(gint fd, guint flags)
357 +{
358 +  return log_transport_plain_new_with_callback(fd, flags, NULL, NULL);
359 +}
360 diff -U5 -rb syslog-ng-3.0.4-orig/src/logtransport.h syslog-ng-3.0.4/src/logtransport.h
361 --- syslog-ng-3.0.4-orig/src/logtransport.h     2009-04-30 10:46:55.000000000 +0200
362 +++ syslog-ng-3.0.4/src/logtransport.h  2009-08-17 11:00:58.000000000 +0200
363 @@ -57,10 +57,12 @@
364  log_transport_read(LogTransport *self, gpointer buf, gsize count, GSockAddr **sa)
365  {
366    return self->read(self, buf, count, sa);
367  }
368  
369 +typedef void (*LogTransportCallback)(gint fd, void *context);
370 +LogTransport *log_transport_plain_new_with_callback(gint fd, guint flags, LogTransportCallback callback, void *context);
371  LogTransport *log_transport_plain_new(gint fd, guint flags);
372  void log_transport_free(LogTransport *s);
373  void log_transport_free_method(LogTransport *s);
374  
375          
376         
This page took 0.077515 seconds and 2 git commands to generate.