]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: log: make sess_build_logline() support being called with no stream
authorWilly Tarreau <w@1wt.eu>
Wed, 5 Sep 2018 14:55:15 +0000 (16:55 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 6 Sep 2018 07:43:06 +0000 (09:43 +0200)
Till now it was impossible to emit logs from the lower layers only because
a stream was mandatory. From now on it will at least be possible to emit a
log to report a bad request or some timings for example. When the stream
is null, sess_build_logline() will use default values and will extract the
timing information from the session just like stream_new() does, so the
resulting log line is perfectly valid.

The termination state will indicate a proxy error during the request phase
since it is the only realistic use for such a call with no stream.

src/log.c

index 52223e9bf2bdc62a176e506d2534adafe3e8198f..8e1453044ac995fc7c73ab7fb223e2c12db4ceb7 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1566,17 +1566,18 @@ void deinit_log_buffers()
 /* Builds a log line in <dst> based on <list_format>, and stops before reaching
  * <maxsize> characters. Returns the size of the output string in characters,
  * not counting the trailing zero which is always added if the resulting size
- * is not zero. It requires a session and a stream.
+ * is not zero. It requires a valid session and optionally a stream. If the
+ * stream is NULL, default values will be assumed for the stream part.
  */
 int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct list *list_format)
 {
        struct proxy *fe = sess->fe;
-       struct proxy *be = s ? s->be : fe;
-       struct http_txn *txn = s ? s->txn : NULL;
-       const struct strm_logs *logs = s ? &s->logs : NULL;
-       const struct connection *be_conn = s ? cs_conn(objt_cs(s->si[1].end)) : NULL;
-       unsigned int s_flags = s ? s->flags : 0;
-       unsigned int uniq_id = s ? s->uniq_id : 0;
+       struct proxy *be;
+       struct http_txn *txn;
+       const struct strm_logs *logs;
+       const struct connection *be_conn;
+       unsigned int s_flags;
+       unsigned int uniq_id;
        struct buffer chunk;
        char *uri;
        char *spc;
@@ -1592,9 +1593,49 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
        int iret;
        struct logformat_node *tmp;
        struct timeval tv;
+       struct strm_logs tmp_strm_log;
 
        /* FIXME: let's limit ourselves to frontend logging for now. */
 
+       if (likely(s)) {
+               be = s->be;
+               txn = s->txn;
+               be_conn = cs_conn(objt_cs(s->si[1].end));
+               s_flags = s->flags;
+               uniq_id = s->uniq_id;
+               logs = &s->logs;
+       } else {
+               /* we have no stream so we first need to initialize a few
+                * things that are needed later. We do increment the request
+                * ID so that it's uniquely assigned to this request just as
+                * if the request had reached the point of being processed.
+                * A request error is reported as it's the only element we have
+                * here and which justifies emitting such a log.
+                */
+               be = fe;
+               txn = NULL;
+               be_conn = NULL;
+               s_flags = SF_ERR_PRXCOND | SF_FINST_R;
+               uniq_id = HA_ATOMIC_XADD(&global.req_count, 1);
+
+               /* prepare a valid log structure */
+               tmp_strm_log.tv_accept = sess->tv_accept;
+               tmp_strm_log.accept_date = sess->accept_date;
+               tmp_strm_log.t_handshake = sess->t_handshake;
+               tmp_strm_log.t_idle = tv_ms_elapsed(&sess->tv_accept, &now) - sess->t_handshake;
+               tv_zero(&tmp_strm_log.tv_request);
+               tmp_strm_log.t_queue = -1;
+               tmp_strm_log.t_connect = -1;
+               tmp_strm_log.t_data = -1;
+               tmp_strm_log.t_close = tv_ms_elapsed(&sess->tv_accept, &now);
+               tmp_strm_log.bytes_in = 0;
+               tmp_strm_log.bytes_out = 0;
+               tmp_strm_log.prx_queue_pos = 0;
+               tmp_strm_log.srv_queue_pos = 0;
+
+               logs = &tmp_strm_log;
+       }
+
        t_request = -1;
        if (tv_isge(&logs->tv_request, &logs->tv_accept))
                t_request = tv_ms_elapsed(&logs->tv_accept, &logs->tv_request);