Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow flux-logger(1) and flux_log(3) to get an EPERM error, optionally #1000

Merged
merged 9 commits into from
Mar 10, 2017
20 changes: 9 additions & 11 deletions doc/man1/flux-logger.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,27 @@ SYNOPSIS

DESCRIPTION
-----------
flux-logger(1) creates Flux log entries. Log entries are sent to
the local Flux communications broker, then forwarded to the
root of the overlay network, where they are disposed of according
to the logging configuration of the communications session.
flux-logger(1) appends Flux log entries to the local Flux
broker's circular buffer.

Log entries are associated with a syslog(3) style severity.
Valid severity names are 'emerg', 'alert', 'crit', 'err',
'warning', 'notice', 'info', 'debug'.

Log entries may also have an application name (default 'logger').

Log entries are timestamped with the wall clock time, as
reported by gettimeofday(2) at the point of origin, and with
the rank of the communications broker originating the message.
Log entries may also have a user-defined application name.
This is different than the syslog 'facility', which is always set
to LOG_USER in Flux log messages.

The wall clock time (UTC) and the broker rank are added to the log
message when it is created.

OPTIONS
-------
*-s, --severity*='SEVERITY'::
Specify the log message severity. The default severity is 'info'.

*-n, --appname*='NAME'::
Specify an application name to associate with the log message.
Specify a user-defined application name to associate with the log message.
The default appname is 'logger'.

AUTHOR
Expand All @@ -58,4 +56,4 @@ include::COPYRIGHT.adoc[]

SEE ALSO
--------
syslog(3)
flux-dmesg(1), flux_log(3), syslog(3)
15 changes: 12 additions & 3 deletions doc/man3/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ MAN3_FILES_PRIMARY = \
flux_reactor_now.3 \
flux_request_decode.3 \
flux_event_decode.3 \
flux_content_load.3
flux_content_load.3 \
flux_log.3

# These files are generated as roff .so includes of a primary page.
# A2X handles this automatically if mentioned in NAME section
Expand Down Expand Up @@ -92,6 +93,7 @@ MAN3_FILES_SECONDARY = \
flux_msg_handler_delvec.3 \
flux_child_watcher_get_rpid.3 \
flux_child_watcher_get_rstatus.3 \
flux_signal_watcher_get_signum.3 \
flux_stat_watcher_get_rstat.3 \
flux_rpc_get_raw.3 \
flux_respond_raw.3 \
Expand All @@ -102,9 +104,12 @@ MAN3_FILES_SECONDARY = \
flux_event_decodef.3 \
flux_event_encode.3 \
flux_event_encodef.3 \
flux_content_load_get.3
flux_content_load_get.3 \
flux_content_store.3 \
flux_content_store_get.3
flux_content_store_get.3 \
flux_vlog.3 \
flux_log_set_appname.3 \
flux_log_set_procid.3

ADOC_FILES = $(MAN3_FILES_PRIMARY:%.3=%.adoc)
XML_FILES = $(MAN3_FILES_PRIMARY:%.3=%.xml)
Expand Down Expand Up @@ -177,6 +182,7 @@ flux_msg_handler_stop.3: flux_msg_handler_create.3
flux_msg_handler_delvec.3: flux_msg_handler_addvec.3
flux_child_watcher_get_rpid.3: flux_child_watcher_create.3
flux_child_watcher_get_rstatus.3: flux_child_watcher_create.3
flux_signal_watcher_get_signum.3: flux_signal_watcher_create.3
flux_stat_watcher_get_rstat.3: flux_stat_watcher_create.3
flux_rpc_get_raw.3: flux_rpc_raw.3
flux_respond_raw.3: flux_respond.3
Expand All @@ -190,6 +196,9 @@ flux_event_encodef.3: flux_event_decode.3
flux_content_load_get.3: flux_content_load.3
flux_content_store.3: flux_content_load.3
flux_content_store_get.3: flux_content_load.3
flux_vlog.3: flux_log.3
flux_log_set_appname.3: flux_log.3
flux_log_set_procid.3: flux_log.3

flux_open.3: topen.c
flux_send.3: tsend.c
Expand Down
132 changes: 132 additions & 0 deletions doc/man3/flux_log.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
flux_log(3)
===========
:doctype: manpage


NAME
----
flux_log, flux_vlog, flux_log_set_appname, flux_log_set_procid - Log messages to the Flux Message Broker


SYNOPSIS
--------
#include <flux/core.h>

int flux_vlog (flux_t *h, int level, const char *fmt, va_list ap);

int flux_log (flux_t *h, int level, const char *fmt, ...);

void flux_log_set_appname (flux_t *h, const char *s);

void flux_log_set_procid (flux_t *h, const char *s);

DESCRIPTION
-----------

`flux_log()` creates RFC 5424 format log messages and sends them
to the Flux message broker on 'h' for handling.

The 'level' parameter should be set to one of the syslog(3) severity
levels, which are, in order of decreasing importance:

'LOG_EMERG':: system is unusable
'LOG_ALERT':: action must be taken immediately
'LOG_CRIT':: critical conditions
'LOG_ERR':: error conditions
'LOG_WARNING':: warning conditions
'LOG_NOTICE':: normal, but significant, condition
'LOG_INFO':: informational message
'LOG_DEBUG':: debug-level message

In addition, the flag 'FLUX_LOG_CHECK' may be logically ORed with
the 'level' to direct `flux_log()` to wait for a response from the broker
indicating whether the log request was accepted or not. Otherwise, log
requests are "fire and forget".

Log messages are are added to the broker's circular buffer which
can be accessed with flux-dmesg(3). From there, a message's disposition
is up to the broker's log configuration.

`flux_log_set_procid()` may be used to override the default procid,
which is initialized to the calling process's PID.

`flux_log_set_appname()` may be used to override the default
application name, which is initialized to the value of the '__progname'
symbol (normally the argv[0] program name).

MAPPING TO SYSLOG
-----------------

A Flux log message is formatted as a Flux request with a "raw" payload,
as defined by Flux RFC 3. The raw payload is formatted according to
Internet RFC 5424.

The following Syslog header fields are set in a Flux log messages when it is
created within `flux_log()`:

PRI::
Set to the user-specified severity level combined with the facility,
which is hardwired to 'LOG_USER' in Flux log messages.

VERSION::
Set to 1.

TIMESTAMP::
Set to the current UTC wallclock time.

HOSTNAME::
Set to the broker rank associated with 'h'.

APP-NAME::
Set to the user-defined application name, truncated to 48 characters,
excluding terminating NULL.

PROCID::
Set to the PID of the calling process.

MSGID::
Set to the NIL string "-".

The STRUCTURED-DATA portion of the message is empty, and reserved for
future use by Flux.

The MSG portion is post-processed to ensure it contains no NULL's or non-ASCII
characters. At this time non-ASCII UTF-8 is not supported by `flux_log()`.

RETURN VALUE
------------

`flux_log()` normally returns 0 with no possibility of error.
However, if the 'FLUX_LOG_CHECK' check flag is specified, it may
return -1 with errno set on error.


ERRORS
------

EPERM::
The user does not have permission to log messages to this Flux instance.

ENOMEM::
Out of memory.


AUTHOR
------
This page is maintained by the Flux community.


RESOURCES
---------
Github: <http://github.com/flux-framework>


COPYRIGHT
---------
include::COPYRIGHT.adoc[]


SEE ALSO
--------
flux-dmesg(1), flux-logger(1),
https://tools.ietf.org/html/rfc5424[RFC 5424 The Syslog Protocol]
20 changes: 17 additions & 3 deletions src/broker/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,14 +525,28 @@ static void append_request_cb (flux_t *h, flux_msg_handler_t *w,
const flux_msg_t *msg, void *arg)
{
logbuf_t *logbuf = arg;
uint32_t matchtag;
const char *buf;
int len;

if (flux_request_decode_raw (msg, NULL, &buf, &len) < 0) {
log_msg ("%s: decode error", __FUNCTION__);
if (flux_msg_get_matchtag (msg, &matchtag) < 0) {
log_msg ("%s: malformed log request", __FUNCTION__);
return;
}
(void)logbuf_append (logbuf, buf, len);
if (flux_request_decode_raw (msg, NULL, &buf, &len) < 0)
goto error;
if (logbuf_append (logbuf, buf, len) < 0)
goto error;
if (matchtag != FLUX_MATCHTAG_NONE) {
if (flux_respond (h, msg, 0, NULL) < 0)
log_err ("%s: error responding to log request", __FUNCTION__);
}
return;
error:
if (matchtag != FLUX_MATCHTAG_NONE) {
if (flux_respond (h, msg, errno, NULL) < 0)
log_err ("%s: error responding to log request", __FUNCTION__);
}
}

static void clear_request_cb (flux_t *h, flux_msg_handler_t *w,
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/flux-logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ int main (int argc, char *argv[])
log_err_exit ("flux_open");

flux_log_set_appname (h, appname);
flux_log (h, severity, "%s", message);
if (flux_log (h, severity | FLUX_LOG_CHECK, "%s", message) < 0)
log_err_exit ("flux_log");

flux_close (h);

Expand Down
9 changes: 6 additions & 3 deletions src/common/libflux/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,16 @@ int flux_sleep_on (flux_t *h, struct flux_match match)

static void call_handler (flux_msg_handler_t *w, const flux_msg_t *msg)
{
uint32_t rolemask;
uint32_t rolemask, matchtag;

if (flux_msg_get_rolemask (msg, &rolemask) < 0)
return;
if (!(rolemask & w->rolemask)) {
if (flux_msg_cmp (msg, FLUX_MATCH_REQUEST))
(void)flux_respond (w->d->h, msg, EPERM, NULL);
if (flux_msg_cmp (msg, FLUX_MATCH_REQUEST)
&& flux_msg_get_matchtag (msg, &matchtag) == 0
&& matchtag != FLUX_MATCHTAG_NONE) {
(void)flux_respond (w->d->h, msg, EPERM, NULL);
}
return;
}
w->fn (w->d->h, w, msg, w->arg);
Expand Down
40 changes: 31 additions & 9 deletions src/common/libflux/flog.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,38 @@ const char *flux_strerror (int errnum)
return zmq_strerror (errnum);
}

void flux_vlog (flux_t *h, int level, const char *fmt, va_list ap)
static int log_rpc (flux_t *h, const char *buf, int len, int flags)
{
flux_rpc_t *r = NULL;
int rc = (flags & FLUX_RPC_NORESPONSE) ? 0 : -1;

if (!(r = flux_rpc_raw (h, "log.append", buf, len, FLUX_NODEID_ANY, flags)))
goto done;
if ((flags & FLUX_RPC_NORESPONSE))
goto done;
if (flux_rpc_get (r, NULL) < 0)
goto done;
rc = 0;
done:
flux_rpc_destroy (r);
return rc;
}

int flux_vlog (flux_t *h, int level, const char *fmt, va_list ap)
{
logctx_t *ctx = getctx (h);
int saved_errno = errno;
uint32_t rank;
flux_rpc_t *rpc = NULL;
int len;
char timestamp[WALLCLOCK_MAXLEN];
char hostname[STDLOG_MAX_HOSTNAME + 1];
struct stdlog_header hdr;
int rpc_flags = FLUX_RPC_NORESPONSE;

if ((level & FLUX_LOG_CHECK)) {
rpc_flags &= ~FLUX_RPC_NORESPONSE;
level &= ~FLUX_LOG_CHECK;
}

stdlog_init (&hdr);
hdr.pri = STDLOG_PRI (level, LOG_USER);
Expand All @@ -128,22 +150,22 @@ void flux_vlog (flux_t *h, int level, const char *fmt, va_list ap)
if (ctx->cb) {
ctx->cb (ctx->buf, len, ctx->cb_arg);
} else {
if (!(rpc = flux_rpc_raw (h, "log.append", ctx->buf, len,
FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE)))
goto done;
if (log_rpc (h, ctx->buf, len, rpc_flags) < 0)
return -1;
}
done:
flux_rpc_destroy (rpc);
errno = saved_errno;
return 0;
}

void flux_log (flux_t *h, int lev, const char *fmt, ...)
int flux_log (flux_t *h, int lev, const char *fmt, ...)
{
va_list ap;
int rc;

va_start (ap, fmt);
flux_vlog (h, lev, fmt, ap);
rc = flux_vlog (h, lev, fmt, ap);
va_end (ap);
return rc;
}

void flux_log_verror (flux_t *h, const char *fmt, va_list ap)
Expand Down
9 changes: 7 additions & 2 deletions src/common/libflux/flog.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

#define FLUX_MAX_LOGBUF 2048

/* May be ored with 'level' to cause log request
* to wait for a success/fail response.
*/
#define FLUX_LOG_CHECK 0x1000

typedef void (*flux_log_f)(const char *buf, int len, void *arg);

/* Set log appname for handle instance.
Expand All @@ -25,8 +30,8 @@ void flux_log_set_procid (flux_t *h, const char *s);

/* Log a message at the specified level, as defined for syslog(3).
*/
void flux_vlog (flux_t *h, int level, const char *fmt, va_list ap);
void flux_log (flux_t *h, int level, const char *fmt, ...)
int flux_vlog (flux_t *h, int level, const char *fmt, va_list ap);
int flux_log (flux_t *h, int level, const char *fmt, ...)
__attribute__ ((format (printf, 3, 4)));

/* Log a message at LOG_ERR level, appending a colon, space, and error string.
Expand Down
Loading