timeout srvtimeout (deprecated) X - X X
timeout tarpit X X X X
transparent (deprecated) X - X X
+unique-id-format X X X -
+unique-id-header X X X -
use_backend - X X -
use-server - - X X
------------------------------------+----------+----------+---------+---------
See also: "option transparent"
+unique-id-format <string>
+ Generate a unique ID for each request.
+ May be used in sections : defaults | frontend | listen | backend
+ yes | yes | yes | no
+ Arguments :
+ <string> is a log-format string.
+
+ This keyword creates a ID for each request using the custom log format. A
+ unique ID is useful to trace a request passing through many components of
+ a complex infrastructure. The newly created ID may also be logged using the
+ %ID tag the log-format string.
+
+ The format should be composed from elements that are guaranteed to be
+ unique when combined together. For instance, if multiple haproxy instances
+ are involved, it might be important to include the node name. It is often
+ needed to log the incoming connection's source and destination addresses
+ and ports. Note that since multiple requests may be performed over the same
+ connection, including a request counter may help differentiate them.
+ Similarly, a timestamp may protect against a rollover of the counter.
+ Logging the process ID will avoid collisions after a service restart.
+
+ It is recommended to use hexadecimal notation for many fields since it
+ makes them more compact and saves space in logs.
+
+ Example:
+
+ unique-id-format %{+X}o\ %Ci:%Cp_%Fi:%Fp_%Ts_%rt:%pid
+
+ will generate:
+
+ 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A
+
+ See also: "unique-id-header"
+
+unique-id-header <name>
+ Add a unique ID header in the HTTP request.
+ May be used in sections : defaults | frontend | listen | backend
+ yes | yes | yes | no
+ Arguments :
+ <name> is the name of the header.
+
+ Add a unique-id header in the HTTP request sent to the server, using the
+ unique-id-format. It can't work if the unique-id-format doesn't exist.
+
+ Example:
+
+ unique-id-format %{+X}o\ %Ci:%Cp_%Fi:%Fp_%Ts_%rt:%pid
+ unique-id-header X-Unique-ID
+
+ will generate:
+
+ X-Unique-ID: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A
+
+ See also: "unique-id-format"
use_backend <backend> if <condition>
use_backend <backend> unless <condition>
| | %Fi | frontend_ip | IP |
| | %Fp | frontend_port | numeric |
| | %H | hostname | string |
+ | | %ID | unique-id | string |
| | %Si | server_IP | IP |
| | %Sp | server_port | numeric |
| | %T | gmt_date_time | date |
#include <types/session.h>
extern struct pool_head *pool2_requri;
+extern struct pool_head *pool2_uniqueid;
extern char *log_format;
extern char default_tcp_log_format[];
#define NB_LOG_FACILITIES 24
#define NB_LOG_LEVELS 8
#define SYSLOG_PORT 514
+#define UNIQUEID_LEN 128
+
/* lists of fields that can be logged */
enum {
LOG_FMT_HDRRESPONSLIST,
LOG_FMT_REQ,
LOG_FMT_HOSTNAME,
+ LOG_FMT_UNIQUEID,
};
/* enum for parse_logformat */
struct proxy *next;
struct list logsrvs;
struct list logformat; /* log_format linked list */
+ char *header_unique_id; /* unique-id header */
+ struct list format_unique_id; /* unique-id format */
int to_log; /* things to be logged (LW_*) */
int stop_time; /* date to stop listening, when stopping != 0 (int ticks) */
struct hdr_exp *req_exp; /* regular expressions for request headers */
void (*srv_error)(struct session *s, /* the function to call upon unrecoverable server errors (or NULL) */
struct stream_interface *si);
unsigned int uniq_id; /* unique ID used for the traces */
+ char *unique_id; /* custom unique ID */
};
/* parameters to configure tracked counters */
LIST_ADDQ(&curproxy->logformat, &node->list);
}
+ /* copy default unique_id to curproxy */
+ list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
+ struct logformat_node *node = malloc(sizeof(struct logformat_node));
+ memcpy(node, tmplf, sizeof(struct logformat_node));
+ LIST_INIT(&node->list);
+ LIST_ADDQ(&curproxy->format_unique_id, &node->list);
+ }
+
+ /* copy default header unique id */
+ if (defproxy.header_unique_id)
+ curproxy->header_unique_id = strdup(defproxy.header_unique_id);
+
curproxy->grace = defproxy.grace;
curproxy->conf.used_listener_id = EB_ROOT;
curproxy->conf.used_server_id = EB_ROOT;
newsrv->prev_state = newsrv->state;
}
}
+
+ else if (strcmp(args[0], "unique-id-format") == 0) {
+ if (!*(args[1])) {
+ Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
+ }
+
+ else if (strcmp(args[0], "unique-id-header") == 0) {
+ if (!*(args[1])) {
+ Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ free(curproxy->header_unique_id);
+ curproxy->header_unique_id = strdup(args[1]);
+ }
+
else if (strcmp(args[0], "log-format") == 0) {
if (!*(args[1])) {
Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
{ "pid", LOG_FMT_PID, PR_MODE_TCP, NULL }, /* log pid */
{ "rt", LOG_FMT_COUNTER, PR_MODE_TCP, NULL }, /* log counter */
{ "H", LOG_FMT_HOSTNAME, PR_MODE_TCP, NULL }, /* Hostname */
+ { "ID", LOG_FMT_UNIQUEID, PR_MODE_HTTP, NULL }, /* Unique ID */
{ 0, 0, 0, NULL }
};
last_isspace = 0;
}
break;
+
+ case LOG_FMT_UNIQUEID: // %ID
+ src = s->unique_id;
+ ret = lf_text(tmplog, src, maxsize - (tmplog - dst), tmp);
+ if (ret == NULL)
+ goto out;
+ tmplog = ret;
+ last_isspace = 0;
+ break;
+
}
}
/* memory allocations */
pool2_requri = create_pool("requri", REQURI_LEN, MEM_F_SHARED);
pool2_capture = create_pool("capture", CAPTURE_LEN, MEM_F_SHARED);
+ pool2_uniqueid = create_pool("uniqueid", UNIQUEID_LEN, MEM_F_SHARED);
}
/*
extern const char *monthname[12];
struct pool_head *pool2_requri;
struct pool_head *pool2_capture;
+struct pool_head *pool2_uniqueid;
/*
* Capture headers from message starting at <som> according to header list
}
}
+ if (!LIST_ISEMPTY(&s->fe->format_unique_id)) {
+ s->unique_id = pool_alloc2(pool2_uniqueid);
+ }
+
/* 4. We may have to convert HTTP/0.9 requests to HTTP/1.0 */
if (unlikely(msg->sl.rq.v_l == 0) && !http_upgrade_v09_to_v10(req, msg, txn))
goto return_bad_req;
get_srv_from_appsession(s, msg->sol + msg->sl.rq.u, msg->sl.rq.u_l);
}
+ /* add unique-id if "header-unique-id" is specified */
+
+ if (!LIST_ISEMPTY(&s->fe->format_unique_id))
+ build_logline(s, s->unique_id, UNIQUEID_LEN, &s->fe->format_unique_id);
+
+ if (s->fe->header_unique_id && s->unique_id) {
+ int ret = snprintf(trash, global.tune.bufsize, "%s: %s", s->fe->header_unique_id, s->unique_id);
+ if (ret < 0 || ret > global.tune.bufsize)
+ goto return_bad_req;
+ if(unlikely(http_header_add_tail(req, &txn->req, &txn->hdr_idx, trash) < 0))
+ goto return_bad_req;
+ }
+
/*
* 9: add X-Forwarded-For if either the frontend or the backend
* asks for it.
pool_free2(pool2_capture, txn->cli_cookie);
pool_free2(pool2_capture, txn->srv_cookie);
pool_free2(apools.sessid, txn->sessid);
+ pool_free2(pool2_uniqueid, s->unique_id);
+ s->unique_id = NULL;
txn->sessid = NULL;
txn->uri = NULL;
txn->srv_cookie = NULL;
LIST_INIT(&p->listener_queue);
LIST_INIT(&p->logsrvs);
LIST_INIT(&p->logformat);
+ LIST_INIT(&p->format_unique_id);
/* Timeouts are defined as -1 */
proxy_reset_timeouts(p);