mirror of
https://github.com/curl/curl.git
synced 2025-09-15 08:32:41 +03:00
tool: add curl command line option --trace-ids
- added and documented --trace-ids to prepend (after the timestamp) the transfer and connection identifiers to each verbose log line - format is [n-m] with `n` being the transfer id and `m` being the connection id. In case there is not valid connection id, print 'x'. - Log calls with a handle that has no transfer id yet, are written without any ids. Closes #11185
This commit is contained in:
parent
e024d5665d
commit
f06cc4f85e
|
@ -64,6 +64,17 @@
|
||||||
|
|
||||||
curl --trace-ascii d.txt --trace-time http://example.com/
|
curl --trace-ascii d.txt --trace-time http://example.com/
|
||||||
|
|
||||||
|
## See which Transfer
|
||||||
|
|
||||||
|
When doing parallel transfers, it is relevant to see which transfer is
|
||||||
|
doing what. When response headers are received (and logged) you need to
|
||||||
|
know which transfer these are for.
|
||||||
|
[`--trace-ids`](https://curl.se/docs/manpage.html#--trace-ids) option
|
||||||
|
is what you need. It will prepend the transfer and connection identifier
|
||||||
|
to each trace output line:
|
||||||
|
|
||||||
|
curl --trace-ascii d.txt --trace-ids http://example.com/
|
||||||
|
|
||||||
## See the Response
|
## See the Response
|
||||||
|
|
||||||
By default curl sends the response to stdout. You need to redirect it
|
By default curl sends the response to stdout. You need to redirect it
|
||||||
|
|
|
@ -265,6 +265,7 @@ DPAGES = \
|
||||||
tlsv1.d \
|
tlsv1.d \
|
||||||
tr-encoding.d \
|
tr-encoding.d \
|
||||||
trace-ascii.d \
|
trace-ascii.d \
|
||||||
|
trace-ids.d \
|
||||||
trace-time.d \
|
trace-time.d \
|
||||||
trace.d \
|
trace.d \
|
||||||
unix-socket.d \
|
unix-socket.d \
|
||||||
|
|
12
docs/cmdline-opts/trace-ids.d
Normal file
12
docs/cmdline-opts/trace-ids.d
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
SPDX-License-Identifier: curl
|
||||||
|
Long: trace-ids
|
||||||
|
Help: Add transfer and connection identifiers to trace/verbose output
|
||||||
|
Added: 8.2.0
|
||||||
|
Category: verbose
|
||||||
|
Example: --trace-ids --trace-ascii output $URL
|
||||||
|
See-also: trace verbose
|
||||||
|
Multi: boolean
|
||||||
|
Scope: global
|
||||||
|
---
|
||||||
|
Prepends the transfer and connection identifiers to each trace or verbose line that curl displays.
|
|
@ -7,7 +7,7 @@ Mutexed: verbose trace-ascii
|
||||||
Category: verbose
|
Category: verbose
|
||||||
Example: --trace log.txt $URL
|
Example: --trace log.txt $URL
|
||||||
Added: 7.9.7
|
Added: 7.9.7
|
||||||
See-also: trace-ascii trace-time
|
See-also: trace-ascii trace-ids trace-time
|
||||||
Multi: single
|
Multi: single
|
||||||
Scope: global
|
Scope: global
|
||||||
---
|
---
|
||||||
|
|
|
@ -252,6 +252,7 @@
|
||||||
--tr-encoding 7.21.6
|
--tr-encoding 7.21.6
|
||||||
--trace 7.9.7
|
--trace 7.9.7
|
||||||
--trace-ascii 7.9.7
|
--trace-ascii 7.9.7
|
||||||
|
--trace-ids 8.2.0
|
||||||
--trace-time 7.14.0
|
--trace-time 7.14.0
|
||||||
--unix-socket 7.40.0
|
--unix-socket 7.40.0
|
||||||
--upload-file (-T) 4.0
|
--upload-file (-T) 4.0
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
#include "memdebug.h" /* keep this as LAST include */
|
#include "memdebug.h" /* keep this as LAST include */
|
||||||
|
|
||||||
static void dump(const char *timebuf, const char *text,
|
static void dump(const char *timebuf, const char *idsbuf, const char *text,
|
||||||
FILE *stream, const unsigned char *ptr, size_t size,
|
FILE *stream, const unsigned char *ptr, size_t size,
|
||||||
trace tracetype, curl_infotype infotype);
|
trace tracetype, curl_infotype infotype);
|
||||||
|
|
||||||
|
@ -67,7 +67,8 @@ static const char *hms_for_sec(time_t tv_sec)
|
||||||
return hms_buf;
|
return hms_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_line_start(FILE *log, const char *intro, curl_infotype type)
|
static void log_line_start(FILE *log, const char *timebuf,
|
||||||
|
const char *idsbuf, curl_infotype type)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is the trace look that is similar to what libcurl makes on its
|
* This is the trace look that is similar to what libcurl makes on its
|
||||||
|
@ -76,12 +77,15 @@ static void log_line_start(FILE *log, const char *intro, curl_infotype type)
|
||||||
static const char * const s_infotype[] = {
|
static const char * const s_infotype[] = {
|
||||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} "
|
"* ", "< ", "> ", "{ ", "} ", "{ ", "} "
|
||||||
};
|
};
|
||||||
if(intro && *intro)
|
if((timebuf && *timebuf) || (idsbuf && *idsbuf))
|
||||||
fprintf(log, "%s%s", intro, s_infotype[type]);
|
fprintf(log, "%s%s%s", timebuf, idsbuf, s_infotype[type]);
|
||||||
else
|
else
|
||||||
fputs(s_infotype[type], log);
|
fputs(s_infotype[type], log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "
|
||||||
|
#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \
|
||||||
|
CURL_FORMAT_CURL_OFF_T "] "
|
||||||
/*
|
/*
|
||||||
** callback for CURLOPT_DEBUGFUNCTION
|
** callback for CURLOPT_DEBUGFUNCTION
|
||||||
*/
|
*/
|
||||||
|
@ -95,6 +99,13 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
const char *text;
|
const char *text;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char timebuf[20];
|
char timebuf[20];
|
||||||
|
/* largest signed 64bit is: 9,223,372,036,854,775,807
|
||||||
|
* max length in decimal: 1 + (6*3) = 19
|
||||||
|
* formatted via TRC_IDS_FORMAT_IDS_2 this becomes 2 + 19 + 1 + 19 + 2 = 43
|
||||||
|
* negative xfer-id are not printed, negative conn-ids use TRC_IDS_FORMAT_1
|
||||||
|
*/
|
||||||
|
char idsbuf[60];
|
||||||
|
curl_off_t xfer_id, conn_id;
|
||||||
|
|
||||||
(void)handle; /* not used */
|
(void)handle; /* not used */
|
||||||
|
|
||||||
|
@ -106,6 +117,20 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
else
|
else
|
||||||
timebuf[0] = 0;
|
timebuf[0] = 0;
|
||||||
|
|
||||||
|
if(handle && config->traceids &&
|
||||||
|
!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
|
||||||
|
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
|
||||||
|
conn_id >= 0) {
|
||||||
|
msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
|
||||||
|
xfer_id, conn_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
idsbuf[0] = 0;
|
||||||
|
|
||||||
if(!config->trace_stream) {
|
if(!config->trace_stream) {
|
||||||
/* open for append */
|
/* open for append */
|
||||||
if(!strcmp("-", config->trace_dump))
|
if(!strcmp("-", config->trace_dump))
|
||||||
|
@ -139,7 +164,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
for(i = 0; i < size - 1; i++) {
|
for(i = 0; i < size - 1; i++) {
|
||||||
if(data[i] == '\n') { /* LF */
|
if(data[i] == '\n') { /* LF */
|
||||||
if(!newl) {
|
if(!newl) {
|
||||||
log_line_start(output, timebuf, type);
|
log_line_start(output, timebuf, idsbuf, type);
|
||||||
}
|
}
|
||||||
(void)fwrite(data + st, i - st + 1, 1, output);
|
(void)fwrite(data + st, i - st + 1, 1, output);
|
||||||
st = i + 1;
|
st = i + 1;
|
||||||
|
@ -147,7 +172,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!newl)
|
if(!newl)
|
||||||
log_line_start(output, timebuf, type);
|
log_line_start(output, timebuf, idsbuf, type);
|
||||||
(void)fwrite(data + st, i - st + 1, 1, output);
|
(void)fwrite(data + st, i - st + 1, 1, output);
|
||||||
}
|
}
|
||||||
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
|
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
|
||||||
|
@ -156,7 +181,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
case CURLINFO_TEXT:
|
case CURLINFO_TEXT:
|
||||||
case CURLINFO_HEADER_IN:
|
case CURLINFO_HEADER_IN:
|
||||||
if(!newl)
|
if(!newl)
|
||||||
log_line_start(output, timebuf, type);
|
log_line_start(output, timebuf, idsbuf, type);
|
||||||
(void)fwrite(data, size, 1, output);
|
(void)fwrite(data, size, 1, output);
|
||||||
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
|
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
|
||||||
traced_data = FALSE;
|
traced_data = FALSE;
|
||||||
|
@ -172,7 +197,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
function */
|
function */
|
||||||
if(!config->isatty || ((output != stderr) && (output != stdout))) {
|
if(!config->isatty || ((output != stderr) && (output != stdout))) {
|
||||||
if(!newl)
|
if(!newl)
|
||||||
log_line_start(output, timebuf, type);
|
log_line_start(output, timebuf, idsbuf, type);
|
||||||
fprintf(output, "[%zu bytes data]\n", size);
|
fprintf(output, "[%zu bytes data]\n", size);
|
||||||
newl = FALSE;
|
newl = FALSE;
|
||||||
traced_data = TRUE;
|
traced_data = TRUE;
|
||||||
|
@ -190,7 +215,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case CURLINFO_TEXT:
|
case CURLINFO_TEXT:
|
||||||
fprintf(output, "%s== Info: %.*s", timebuf, (int)size, data);
|
fprintf(output, "%s%s== Info: %.*s", timebuf, idsbuf, (int)size, data);
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default: /* in case a new one is introduced to shock us */
|
default: /* in case a new one is introduced to shock us */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -215,12 +240,12 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dump(timebuf, text, output, (unsigned char *) data, size, config->tracetype,
|
dump(timebuf, idsbuf, text, output, (unsigned char *) data, size,
|
||||||
type);
|
config->tracetype, type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump(const char *timebuf, const char *text,
|
static void dump(const char *timebuf, const char *idsbuf, const char *text,
|
||||||
FILE *stream, const unsigned char *ptr, size_t size,
|
FILE *stream, const unsigned char *ptr, size_t size,
|
||||||
trace tracetype, curl_infotype infotype)
|
trace tracetype, curl_infotype infotype)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +258,8 @@ static void dump(const char *timebuf, const char *text,
|
||||||
/* without the hex output, we can fit more on screen */
|
/* without the hex output, we can fit more on screen */
|
||||||
width = 0x40;
|
width = 0x40;
|
||||||
|
|
||||||
fprintf(stream, "%s%s, %zu bytes (0x%zx)\n", timebuf, text, size, size);
|
fprintf(stream, "%s%s%s, %zu bytes (0x%zx)\n", timebuf, idsbuf,
|
||||||
|
text, size, size);
|
||||||
|
|
||||||
for(i = 0; i < size; i += width) {
|
for(i = 0; i < size; i += width) {
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,7 @@ struct GlobalConfig {
|
||||||
bool trace_fopened;
|
bool trace_fopened;
|
||||||
trace tracetype;
|
trace tracetype;
|
||||||
bool tracetime; /* include timestamp? */
|
bool tracetime; /* include timestamp? */
|
||||||
|
bool traceids; /* include xfer-/conn-id? */
|
||||||
int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
|
int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
|
||||||
char *libcurl; /* Output libcurl code to this file name */
|
char *libcurl; /* Output libcurl code to this file name */
|
||||||
bool fail_early; /* exit on first transfer error */
|
bool fail_early; /* exit on first transfer error */
|
||||||
|
|
|
@ -205,6 +205,7 @@ static const struct LongShort aliases[]= {
|
||||||
{"$Z", "compressed-ssh", ARG_BOOL},
|
{"$Z", "compressed-ssh", ARG_BOOL},
|
||||||
{"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
|
{"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
|
||||||
{"$!", "retry-all-errors", ARG_BOOL},
|
{"$!", "retry-all-errors", ARG_BOOL},
|
||||||
|
{"$%", "trace-ids", ARG_BOOL},
|
||||||
{"0", "http1.0", ARG_NONE},
|
{"0", "http1.0", ARG_NONE},
|
||||||
{"01", "http1.1", ARG_NONE},
|
{"01", "http1.1", ARG_NONE},
|
||||||
{"02", "http2", ARG_NONE},
|
{"02", "http2", ARG_NONE},
|
||||||
|
@ -1407,6 +1408,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
||||||
return err;
|
return err;
|
||||||
/* 0 is a valid value for this timeout */
|
/* 0 is a valid value for this timeout */
|
||||||
break;
|
break;
|
||||||
|
case '%': /* --trace-ids */
|
||||||
|
global->traceids = toggle;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
|
|
|
@ -759,6 +759,9 @@ const struct helptxt helptext[] = {
|
||||||
{" --trace-ascii <file>",
|
{" --trace-ascii <file>",
|
||||||
"Like --trace, but without hex output",
|
"Like --trace, but without hex output",
|
||||||
CURLHELP_VERBOSE},
|
CURLHELP_VERBOSE},
|
||||||
|
{" --trace-ids",
|
||||||
|
"Add transfer/connection identifiers to trace/verbose output",
|
||||||
|
CURLHELP_VERBOSE},
|
||||||
{" --trace-time",
|
{" --trace-time",
|
||||||
"Add time stamps to trace/verbose output",
|
"Add time stamps to trace/verbose output",
|
||||||
CURLHELP_VERBOSE},
|
CURLHELP_VERBOSE},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user