diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst index 549f26b0089..39afa7bdbec 100644 --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -11,42 +11,66 @@ This module provides an interface to the Unix ``syslog`` library routines. Refer to the Unix manual pages for a detailed description of the ``syslog`` facility. +This module wraps the system ``syslog`` module. A pure Python +library that can speak to a syslog server is available in +the :mod:`logging.handlers` module as :class:`SysLogHandler`. + The module defines the following functions: .. function:: syslog([priority,] message) - Send the string *message* to the system logger. A trailing newline is added if - necessary. Each message is tagged with a priority composed of a *facility* and - a *level*. The optional *priority* argument, which defaults to - :const:`LOG_INFO`, determines the message priority. If the facility is not - encoded in *priority* using logical-or (``LOG_INFO | LOG_USER``), the value - given in the :func:`openlog` call is used. + Send the string *message* to the system logger. A trailing newline is + added if necessary. Each message is tagged with a priority composed + of a *facility* and a *level*. The optional *priority* argument, which + defaults to :const:`LOG_INFO`, determines the message priority. If the + facility is not encoded in *priority* using logical-or (``LOG_INFO | + LOG_USER``), the value given in the :func:`openlog` call is used. + + If :func:`openlog` has not been called prior to the call to + :func:'syslog', ``openlog()`` will be called with no arguments. -.. function:: openlog(ident[, logopt[, facility]]) +.. function:: openlog([ident[, logopt[, facility]]]) - Logging options other than the defaults can be set by explicitly opening the log - file with :func:`openlog` prior to calling :func:`syslog`. The defaults are - (usually) *ident* = ``'syslog'``, *logopt* = ``0``, *facility* = - :const:`LOG_USER`. The *ident* argument is a string which is prepended to every - message. The optional *logopt* argument is a bit field - see below for possible - values to combine. The optional *facility* argument sets the default facility - for messages which do not have a facility explicitly encoded. + Logging options of subsequent :func:`syslog` calls can be set by + calling :func:`openlog`. :func:`syslog` will call :func:`openlog` + with no arguments if the log is not currently open. + + The optional *ident* keyword argument is a string which is prepended + to every message, and defaults to ''sys.argv[0]'' with leading + path components stripped. The optional *logopt* keyword argument + (default=0) is a bit field - see below for possible values to combine. + The optional *facility* keyword argument (default=:const:`LOG_USER`) + sets the default facility for messages which do not have a facility + explicitly encoded. + + .. versionchanged::3.2 + In previous versions, keyword arguments were not allowed, and *ident* + was required. The default for *ident* was dependent on the system + libraries, and often was ''python'' instead of the name of the + python program file. .. function:: closelog() - Close the log file. + Reset the syslog module values and call the system library + ''closelog()''. + + This causes the module to behave as it does when initially imported. + For example, :func:'openlog' will be called on the first :func:'syslog' + call (if :func:'openlog' hasn't already been called), and *ident* + and other :func:'openlog' parameters are reset to defaults. .. function:: setlogmask(maskpri) - Set the priority mask to *maskpri* and return the previous mask value. Calls to - :func:`syslog` with a priority level not set in *maskpri* are ignored. The - default is to log all priorities. The function ``LOG_MASK(pri)`` calculates the - mask for the individual priority *pri*. The function ``LOG_UPTO(pri)`` - calculates the mask for all priorities up to and including *pri*. + Set the priority mask to *maskpri* and return the previous mask value. + Calls to :func:`syslog` with a priority level not set in *maskpri* + are ignored. The default is to log all priorities. The function + ``LOG_MASK(pri)`` calculates the mask for the individual priority + *pri*. The function ``LOG_UPTO(pri)`` calculates the mask for all + priorities up to and including *pri*. The module defines the following constants: @@ -64,3 +88,24 @@ Log options: :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT` and :const:`LOG_PERROR` if defined in ````. + +Examples +-------- + +Simple example +~~~~~~~~~~~~~~ + +A simple set of examples:: + + import syslog + + syslog.syslog('Processing started') + if error: + syslog.syslog(syslog.LOG_ERR, 'Processing started') + +An example of setting some log options, these would include the process ID +in logged messages, and write the messages to the destination facility +used for mail logging:: + + syslog.openlog(logopt=syslog.LOG_PID, facility=syslog.LOG_MAIL) + syslog.syslog('E-mail processing initiated...') diff --git a/Misc/NEWS b/Misc/NEWS index dda4164927e..6be66b35bb3 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,10 @@ Core and Builtins Library ------- +- Issue #8451: Syslog module now uses basename(sys.argv[0]) instead of + the string "python" as the *ident*. openlog() arguments are all optional + and keywords. + - Issue #8108: Fix the unwrap() method of SSL objects when the socket has a non-infinite timeout. Also make that method friendlier with applications wanting to continue using the socket in clear-text mode, by disabling diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index 9e1ed0619f1..30d373127ba 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -26,6 +26,11 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Revision history: +2010/04/20 (Sean Reifschneider) + - Use basename(sys.argv[0]) for the default "ident". + - Arguments to openlog() are now keyword args and are all optional. + - syslog() calls openlog() if it hasn't already been called. + 1998/04/28 (Sean Reifschneider) - When facility not specified to syslog() method, use default from openlog() (This is how it was claimed to work in the documentation) @@ -45,6 +50,7 @@ Revision history: /* syslog module */ #include "Python.h" +#include "osdefs.h" #include @@ -52,26 +58,80 @@ Revision history: static PyObject *S_ident_o = NULL; /* identifier, held by openlog() */ +static PyObject * +syslog_get_argv(void) +{ + /* Figure out what to use for as the program "ident" for openlog(). + * This swallows exceptions and continues rather than failing out, + * because the syslog module can still be used because openlog(3) + * is optional. + */ + + Py_ssize_t argv_len; + PyObject *scriptobj; + char *atslash; + PyObject *argv = PySys_GetObject("argv"); + + if (argv == NULL) { + return(NULL); + } + + argv_len = PyList_Size(argv); + if (argv_len == -1) { + PyErr_Clear(); + return(NULL); + } + if (argv_len == 0) { + return(NULL); + } + + scriptobj = PyList_GetItem(argv, 0); + if (!PyString_Check(scriptobj)) { + return(NULL); + } + if (PyString_GET_SIZE(scriptobj) == 0) { + return(NULL); + } + + atslash = strrchr(PyString_AsString(scriptobj), SEP); + if (atslash) { + return(PyString_FromString(atslash + 1)); + } else { + Py_INCREF(scriptobj); + return(scriptobj); + } + + return(NULL); +} + + static PyObject * -syslog_openlog(PyObject * self, PyObject * args) +syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds) { long logopt = 0; long facility = LOG_USER; - PyObject *new_S_ident_o; + PyObject *new_S_ident_o = NULL; + static char *keywords[] = {"ident", "logoption", "facility", 0}; - if (!PyArg_ParseTuple(args, - "S|ll;ident string [, logoption [, facility]]", - &new_S_ident_o, &logopt, &facility)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "|Sll:openlog", keywords, &new_S_ident_o, &logopt, &facility)) return NULL; - /* This is needed because openlog() does NOT make a copy - * and syslog() later uses it.. cannot trash it. - */ + if (new_S_ident_o) { Py_INCREF(new_S_ident_o); } + + /* get either sys.argv[0] or use "python" otherwise */ + if (!new_S_ident_o) { + new_S_ident_o = syslog_get_argv(); + } + Py_XDECREF(S_ident_o); S_ident_o = new_S_ident_o; - Py_INCREF(S_ident_o); - openlog(PyString_AsString(S_ident_o), logopt, facility); + /* At this point, S_ident_o should be INCREF()ed. openlog(3) does not + * make a copy, and syslog(3) later uses it. We can't garbagecollect it + */ + + openlog(S_ident_o ? PyString_AsString(S_ident_o) : NULL, logopt, facility); Py_INCREF(Py_None); return Py_None; @@ -92,6 +152,21 @@ syslog_syslog(PyObject * self, PyObject * args) return NULL; } + /* call openlog if no current identifier */ + if (!S_ident_o) { + PyObject *openargs; + + /* Continue even if PyTuple_New fails, because openlog(3) is optional. + * So, we can still do loggin in the unlikely event things are so hosed + * that we can't do this tuple. + */ + if ((openargs = PyTuple_New(0))) { + PyObject *openlog_ret = syslog_openlog(self, openargs, NULL); + Py_XDECREF(openlog_ret); + Py_DECREF(openargs); + } + } + Py_BEGIN_ALLOW_THREADS; syslog(priority, "%s", message); Py_END_ALLOW_THREADS; @@ -145,7 +220,7 @@ syslog_log_upto(PyObject *self, PyObject *args) /* List of functions defined in the module */ static PyMethodDef syslog_methods[] = { - {"openlog", syslog_openlog, METH_VARARGS}, + {"openlog", (PyCFunction) syslog_openlog, METH_VARARGS | METH_KEYWORDS}, {"closelog", syslog_closelog, METH_NOARGS}, {"syslog", syslog_syslog, METH_VARARGS}, {"setlogmask", syslog_setlogmask, METH_VARARGS},