Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions doc/man1/flux-job.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ SYNOPSIS
| **flux** **job** **purge** [*-f*] [*--age-limit=FSD*] [*--num-limit=N*] [*ids...*]
| **flux** **job** **info** [*--original*] [*--base*] *id* *key*
| **flux** **job** **hostpids** [*OPTIONS*] *id*
| **flux** **job** **eventlog** [*-F*] [*-H*] [*-p PATH*] *id*


DESCRIPTION
Expand Down Expand Up @@ -502,6 +503,40 @@ Options:
(a floating point value with optional suffix ``s`` for seconds,
``m`` for minutes, ``h`` for hours, or ``d`` for days).

eventlog
--------

.. program:: flux job eventlog

:program:`flux job eventlog` prints a job eventlog.

Options:

.. option:: -f, --format=FORMAT

Specify the output FORMAT (text or json). Default: text.

.. option:: -T, --time-format=FORMAT

Specify the timestamp FORMAT (raw, iso, or offset). Default: raw.

.. option:: -H, --human

Display human-readable output.

.. option:: -L, --color=WHEN

Colorize output when supported and WHEN condition is met
(always, never, or auto). Default: always.

.. option:: -F, --follow

Follow events until the job is inactive.

.. option:: -p, --path=PATH

Specify alternate eventlog name or path suffix, e.g. ``exec``, ``output``,
``guest.exec.eventlog``. Default: ``eventlog``.

RESOURCES
=========
Expand Down
44 changes: 27 additions & 17 deletions src/cmd/job/eventlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "src/common/libeventlog/eventlog.h"
#include "src/common/libeventlog/formatter.h"
#include "ccan/str/str.h"
#include "ccan/array_size/array_size.h"
#include "common.h"

struct optparse_option eventlog_opts[] = {
Expand Down Expand Up @@ -114,25 +115,31 @@ struct eventlog_ctx {
struct path_shortname {
const char *name;
const char *path;
const char *end_event;
};

/* Set of shorthand names for common job eventlog paths:
/* Set of shorthand names and RFC-defined terminating event,
* if any, for common job eventlog paths:
*/
struct path_shortname eventlog_paths[] = {
{ "exec", "guest.exec.eventlog" },
{ "output", "guest.output" },
{ "input", "guest.input" },
{ NULL, NULL },
{ "eventlog", "eventlog", "clean" },
{ "exec", "guest.exec.eventlog", "done" },
{ "output", "guest.output", NULL },
{ "input", "guest.input", NULL },
};

const char *path_lookup (const char *name)
const char *path_lookup (const char *name, const char **end_event)
{
const struct path_shortname *path = eventlog_paths;
while (path->name) {
if (streq (name, path->name))
return path->path;
path++;
for (int i = 0; i < ARRAY_SIZE (eventlog_paths); i++) {
const struct path_shortname *entry = &eventlog_paths[i];
if (streq (name, entry->name) || streq (name, entry->path)) {
if (end_event)
*end_event = entry->end_event;
return entry->path;
}
}
if (end_event)
*end_event = NULL;
return name;
}

Expand Down Expand Up @@ -194,7 +201,6 @@ int cmd_eventlog (optparse_t *p, int argc, char **argv)
flux_t *h;
int optindex = optparse_option_index (p);
flux_future_t *f;
const char *topic = "job-info.lookup";
struct eventlog_ctx ctx = {0};

if (!(h = flux_open (NULL, 0)))
Expand All @@ -210,7 +216,7 @@ int cmd_eventlog (optparse_t *p, int argc, char **argv)
if (optparse_hasopt (p, "follow"))
return wait_event_run (p,
ctx.jobid,
"clean",
NULL, // will look up terminating event
optparse_get_str (p, "path", "eventlog"),
NULL,
1,
Expand All @@ -220,14 +226,17 @@ int cmd_eventlog (optparse_t *p, int argc, char **argv)
false);

ctx.id = parse_jobid (ctx.jobid);
ctx.path = path_lookup (optparse_get_str (p, "path", "eventlog"));
ctx.path = path_lookup (optparse_get_str (p, "path", "eventlog"), NULL);
ctx.p = p;

if (!(ctx.evf = eventlog_formatter_create ()))
log_err_exit ("eventlog_formatter_create");
formatter_parse_options (p, ctx.evf);

if (!(f = flux_rpc_pack (h, topic, FLUX_NODEID_ANY, 0,
if (!(f = flux_rpc_pack (h,
"job-info.lookup",
FLUX_NODEID_ANY,
0,
"{s:I s:[s] s:i}",
"id", ctx.id,
"keys", ctx.path,
Expand Down Expand Up @@ -394,8 +403,9 @@ static int wait_event_run (optparse_t *p,
ctx.p = p;
ctx.jobid = jobid;
ctx.id = parse_jobid (ctx.jobid);
ctx.wait_event = wait_event;
ctx.path = path_lookup (path);
ctx.path = path_lookup (path, &ctx.wait_event);
if (wait_event)
ctx.wait_event = wait_event;
ctx.verbose = verbose;
ctx.quiet = quiet;
if ((ctx.count = count) <= 0)
Expand Down
12 changes: 12 additions & 0 deletions t/t2230-job-info-lookup.t
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,18 @@ test_expect_success 'flux job eventlog -p fails on invalid path' '
jobid=$(submit_job) &&
test_must_fail flux job eventlog -p "foobar" $jobid
'
test_expect_success 'flux job eventlog -F -p eventlog terminates on clean' '
jobid=$(submit_job) &&
run_timeout 30 \
flux job eventlog -p eventlog -F $jobid 2>follow_main.err &&
test_cmp /dev/null follow_main.err
'
test_expect_success 'flux job eventlog -F -p exec terminates on done' '
jobid=$(submit_job) &&
run_timeout 30 \
flux job eventlog -p exec -F $jobid 2>follow_exec.err &&
test_cmp /dev/null follow_exec.err
'
# submit job in separate test to avoid using the form:
# jobid=$(flux submit ..) && flux job eventlog $jobid ... &
# which will pick up the wrong $jobid since the pipeline is placed into
Expand Down
Loading