Download raw body.
httpd: add timestamps to fastcgi error log
On Sun Nov 01, 2026 at 06:59:48PM +0100, Rafael Sadowski wrote:
> I don't suppose anyone has ever tried to debug their error logs.
>
> This diff changes the log from:
>
> error.cgi: lab test error, GET /cgi-bin/error.cgi
>
> to:
>
> 01/Nov/2026:18:53:55 +0100: error.cgi: lab test error, GET /cgi-bin/error.cgi
>
> Does anyone have a better idea for a syntax? OK?
>
> Rafael
>
Following feedback, here is the next iteration. This time, ONLY the
error log, including the format as per "syslogd -Z":
2026-11-02T08:49:40.036Z: error.cgi: lab test error, GET /cgi-bin/error.cgi
I don’t want to change the access log at the moment!
commit 8496842a679db367ba919ba9e4ee1b16565b506f
Author: Rafael Sadowski <rafael@sizeofvoid.org>
Date: Sun Nov 1 15:18:04 2026 +0100
httpd: add timestamps to fastcgi error log
When not logging to syslog, prefix FastCGI stderr output with a UTC
timestamp in the same format syslogd -Z uses.
diff --git a/httpd.h b/httpd.h
index a2defd9..0fbad1b 100644
--- a/httpd.h
+++ b/httpd.h
@@ -696,6 +696,7 @@ int server_foreach(int (*)(struct server *,
struct server_config *, void *), void *);
struct server *server_byname(struct server *);
struct server *server_bysocket(struct server *);
+int server_current_time(char *, size_t);
SPLAY_PROTOTYPE(client_tree, client, clt_nodes, server_client_cmp);
diff --git a/server.c b/server.c
index b32a077..ea53802 100644
--- a/server.c
+++ b/server.c
@@ -1560,4 +1560,26 @@ server_client_cmp(struct client *a, struct client *b)
return ((int)a->clt_id - b->clt_id);
}
+int
+server_current_time(char *timestamp, size_t len)
+{
+ struct tm tm;
+ struct timeval now;
+ size_t l;
+ int n;
+
+ if (gettimeofday(&now, NULL) == -1)
+ return (-1);
+ if (gmtime_r(&now.tv_sec, &tm) == NULL)
+ return (-1);
+ if ((l = strftime(timestamp, len, "%FT%T", &tm)) == 0)
+ return (-1);
+ n = snprintf(timestamp + l, len - l, ".%03ldZ",
+ (long)now.tv_usec / 1000);
+ if (n < 0 || (size_t)n >= len - l)
+ return (-1);
+
+ return (0);
+}
+
SPLAY_GENERATE(client_tree, client, clt_nodes, server_client_cmp);
diff --git a/server_fcgi.c b/server_fcgi.c
index 2428adb..ef58c3f 100644
--- a/server_fcgi.c
+++ b/server_fcgi.c
@@ -85,6 +85,7 @@ int server_fcgi_writechunk(struct client *);
int server_fcgi_getheaders(struct client *);
int fcgi_add_param(struct server_fcgi_param *, const char *, const char *,
struct client *);
+void server_fcgi_err_log(struct client *);
int
server_fcgi(struct httpd *env, struct client *clt)
@@ -512,6 +513,32 @@ server_fcgi_error(struct bufferevent *bev, short error, void *arg)
server_file_error(bev, error, arg);
}
+void
+server_fcgi_err_log(struct client *clt)
+{
+ char tstamp[33];
+ struct server_config *srv_conf;
+ size_t len;
+ char *msg;
+
+ if ((srv_conf = clt->clt_srv_conf) == NULL)
+ return;
+
+ if ((len = EVBUFFER_LENGTH(clt->clt_srvevb)) == 0)
+ return;
+
+ if ((msg = get_string(EVBUFFER_DATA(clt->clt_srvevb), len)) == NULL)
+ return;
+
+ if ((srv_conf->flags & SRVFLAG_SYSLOG) == 0 &&
+ server_current_time(tstamp, sizeof(tstamp)) == 0) {
+ server_sendlog(srv_conf, IMSG_LOG_ERROR, "%s: %s", tstamp, msg);
+ } else {
+ server_sendlog(srv_conf, IMSG_LOG_ERROR, "%s", msg);
+ }
+ free(msg);
+}
+
void
server_fcgi_read(struct bufferevent *bev, void *arg)
{
@@ -519,7 +546,6 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
struct client *clt = (struct client *)arg;
struct fcgi_record_header *h;
size_t len;
- char *ptr;
do {
len = bufferevent_read(bev, buf, clt->clt_fcgi.toread);
@@ -561,15 +587,7 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
case FCGI_READ_CONTENT:
switch (clt->clt_fcgi.type) {
case FCGI_STDERR:
- if (EVBUFFER_LENGTH(clt->clt_srvevb) > 0 &&
- (ptr = get_string(
- EVBUFFER_DATA(clt->clt_srvevb),
- EVBUFFER_LENGTH(clt->clt_srvevb))) !=
- NULL) {
- server_sendlog(clt->clt_srv_conf,
- IMSG_LOG_ERROR, "%s", ptr);
- free(ptr);
- }
+ server_fcgi_err_log(clt);
break;
case FCGI_STDOUT:
++clt->clt_chunk;
httpd: add timestamps to fastcgi error log