Hi Douglas,
On Thu, Apr 02, 2015 at 08:28:52PM +0000, Douglas Borg wrote:
> I do think it would be useful for HAProxy to have configuration options to
> print logs directly to stdout/stderr. With container technologies like Docker,
> it is nice to keep to the one process per container rule and not have to run
> rsyslog alongside HAProxy just to ship logs out to stdout/stderr. This also
> fits in nicely with the strategy outlined in http://12factor.net/logs.
>
> Check out https://github.com/dockerfile/haproxy/issues/3.
>
> I think having an easy way to configure haproxy output logs directly to stdout
> and stderr would be much appreciated by anyone trying to fit haproxy into
> thier
> stacks running on containers.
Well, while I understand the benefits of having it for debugging, for
prod it's causing me to get a bit nervous. The problem is that if we
simply write to stdout, we'll cause new classes of issues where people
report pauses or even stalls in the process due to the other side of
the pipe not reading fast enough. Users will say "my disks can write
at 100 MB/s so that cannot be the problem"... while it will definitely
be it. The alternative is to log in non-blocking mode, causing some
writes to be lost when the pipe is full. But that also means that we
can randomly get truncated lines on output when the reader is slow.
A while ago I wanted to implement a logging task with a buffer that
could be used for stream-based logging. In this case it could be
useful and we could even report the number of logs lost.
If you're interested in experimenting, here's a simple patch I just
wrote to allow the logs to be sent to something not a socket when the
"log" directive designates a file/pipe/device/symlink. You can thus
use "log /dev/stdout local0" for example. Note, it's ugly, can only
use synchronous logging, and will only perform the write() when the
sendto() has failed. But that can give you an idea of what could be
achieved this way for certain purposes.
Best regards,
Willy
diff --git a/src/log.c b/src/log.c
index 1a5ad25..ba9f97a 100644
--- a/src/log.c
+++ b/src/log.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <sys/time.h>
+#include <sys/stat.h>
#include <common/config.h>
#include <common/compat.h>
@@ -831,7 +832,17 @@ void __send_log(struct proxy *p, int level, char *message,
size_t size)
/* socket not successfully initialized yet */
int proto = logsrv->addr.ss_family == AF_UNIX ? 0 :
IPPROTO_UDP;
- if ((*plogfd = socket(logsrv->addr.ss_family,
SOCK_DGRAM, proto)) < 0) {
+ if (logsrv->addr.ss_family == AF_UNIX) {
+ struct stat st;
+
+ /* check if this is something not a socket */
+ if (stat(((struct sockaddr_un
*)&logsrv->addr)->sun_path, &st) == 0) {
+ if (!S_ISSOCK(st.st_mode))
+ *plogfd = open(((struct
sockaddr_un *)&logsrv->addr)->sun_path, O_WRONLY);
+ }
+ }
+
+ if (*plogfd < 0 && (*plogfd =
socket(logsrv->addr.ss_family, SOCK_DGRAM, proto)) < 0) {
Alert("socket for logger #%d failed: %s
(errno=%d)\n",
nblogger, strerror(errno), errno);
continue;
@@ -873,6 +884,9 @@ void __send_log(struct proxy *p, int level, char *message,
size_t size)
MSG_DONTWAIT | MSG_NOSIGNAL,
(struct sockaddr *)&logsrv->addr,
get_addr_len(&logsrv->addr));
+ if (sent == -1 && errno == ENOTSOCK)
+ sent = write(*plogfd, log_ptr, max);
+
log_ptr[max - 1] = backup;
if (sent < 0) {