]> mj.ucw.cz Git - libucw.git/blobdiff - ucw/log-conf.c
UCW::CGI -- fixed a bug in parsing of boundaries
[libucw.git] / ucw / log-conf.c
index 5d54d7f35b44e1d009d8835e55bee594d02af92d..d0afece0fb7e650ebe9e6f33157bff9c6dff00dd 100644 (file)
@@ -9,11 +9,13 @@
 
 #include "ucw/lib.h"
 #include "ucw/log.h"
+#include "ucw/log-internal.h"
 #include "ucw/conf.h"
 #include "ucw/simple-lists.h"
 #include "ucw/tbf.h"
 #include "ucw/threads.h"
 
+#include <stdio.h>
 #include <string.h>
 #include <syslog.h>
 #include <sys/time.h>
@@ -33,6 +35,7 @@ struct stream_config {
   int show_types;
   int syslog_pids;
   int errors_fatal;
+  int stderr_follows;
   struct log_stream *ls;
   int mark;                            // Used temporarily in log_config_commit()
 };
@@ -58,12 +61,17 @@ stream_commit(void *ptr)
 {
   struct stream_config *c = ptr;
 
-  if (c->file_name && c->syslog_facility)
-    return "Both FileName and SyslogFacility selected";
-  if (c->syslog_facility && !log_syslog_facility_exists(c->syslog_facility))
-    return cf_printf("SyslogFacility `%s' is not recognized", c->syslog_facility);
-  if (c->syslog_facility && c->microseconds)
-    return "Syslog streams do not support microsecond precision";
+  if (c->syslog_facility)
+    {
+      if (!log_syslog_facility_exists(c->syslog_facility))
+       return cf_printf("SyslogFacility `%s' is not recognized", c->syslog_facility);
+      if (c->file_name)
+       return "Both FileName and SyslogFacility selected";
+      if (c->microseconds)
+       return "Syslog streams do not support microsecond precision";
+    }
+  if (c->stderr_follows && !c->file_name)
+    return "StdErrFollows requires a file-based stream";
   return NULL;
 }
 
@@ -103,6 +111,7 @@ static struct cf_section stream_config = {
     CF_INT("ShowTypes", P(show_types)),
     CF_INT("SyslogPID", P(syslog_pids)),
     CF_INT("ErrorsFatal", P(errors_fatal)),
+    CF_INT("StdErrFollows", P(stderr_follows)),
 #undef P
     CF_END
   }
@@ -216,17 +225,36 @@ log_limiter(struct log_stream *ls, struct log_msg *m)
     return 0;
 
   ASSERT(!(m->flags & L_SIGHANDLER));
-  timestamp_t now = ((timestamp_t) m->tv->tv_sec * 1000) + (m->tv->tv_usec / 1000);
+  if (m->flags & L_LOGGER_ERR)
+    return 0;
 
+  timestamp_t now = ((timestamp_t) m->tv->tv_sec * 1000) + (m->tv->tv_usec / 1000);
   ucwlib_lock();
   int res = tbf_limit(tbf, now);
   ucwlib_unlock();
-  return !res;
+
+  if (res < 0)
+    {
+      if (res == -1)
+       {
+         struct log_msg mm = *m;
+         mm.flags |= L_LOGGER_ERR;
+         mm.raw_msg = "(maximum logging rate exceeded, some messages will be suppressed)";
+         log_pass_msg(0, ls, &mm);
+       }
+      return 1;
+    }
+  else
+    return 0;
 }
 
 static void
 log_apply_limits(struct log_stream *ls, struct limit_config *lim)
 {
+  uns mask = log_type_mask(&lim->types);
+  if (!mask)
+    return;
+
   if (!ls->user_data)
     {
       ls->user_data = cf_malloc_zero(LS_NUM_TYPES * sizeof(struct token_bucket_filter *));
@@ -238,7 +266,6 @@ log_apply_limits(struct log_stream *ls, struct limit_config *lim)
   tbf->burst = lim->burst;
   tbf_init(tbf);
 
-  uns mask = log_type_mask(&lim->types);
   for (uns i=0; i < LS_NUM_TYPES; i++)
     if (mask & (1 << i))
       limits[i] = tbf;
@@ -265,7 +292,7 @@ do_new_configured(struct stream_config *c)
     return c->ls;
 
   if (c->file_name)
-    ls = log_new_file(c->file_name);
+    ls = log_new_file(c->file_name, (c->stderr_follows ? FF_FD2_FOLLOWS : 0));
   else if (c->syslog_facility)
     ls = log_new_syslog(c->syslog_facility, (c->syslog_pids ? LOG_PID : 0));
   else
@@ -313,6 +340,7 @@ log_configured(const char *name)
 
 #ifdef TEST
 
+#include <unistd.h>
 #include "ucw/getopt.h"
 
 int main(int argc, char **argv)
@@ -324,7 +352,12 @@ int main(int argc, char **argv)
 
   int type = log_register_type("foo");
   struct log_stream *ls = log_new_configured("combined");
-  msg(L_INFO | ls->regnum | type, "Hello, universe!");
+  for (uns i=0; i<10; i++)
+    {
+      msg(L_INFO | ls->regnum | type, "Hello, universe!");
+      usleep(200000);
+    }
+  fprintf(stderr, "Alas, this was printed to stderr.\n");
 
   log_close_all();
   return 0;