[issue33506] [logging] template for filename timestamps

2018-05-14 Thread Steve R. Hastings

New submission from Steve R. Hastings :

When a logged file has a timed rotation, it is renamed with an archival 
filename that includes a timestamp.  The logging library has a small set of 
predefined filename templates and no way is provided to override them.

Also, the current rule is that while the file is in active use for logging, it 
will not have a timestamp in the filename; the filename will be something like: 
foo.log

Then, at file rotation time, foo.log is closed and then renamed to an archival 
name that includes a timestamp (something like: foo-2018-05-14.log), and a new 
active log file is opened with the name foo.log again.

Proposed enhancement: it should be possible to provide template codes that 
specify the format of the timestamp, and there should be an option that when 
the file is in active use its filename will include the timestamp.  (Then at 
rotation time, the file is simply closed, with no need to rename it; and a new 
file with a new timestamp is opened.)

For example, specifying a log filename of "foo-%Y%m%d-%H%M%S" would specify a 
filename like: foo-20180514-16.log

Use case: the company that employs me had a logging system requiring both of 
the above features.  The timestamp in the filename had to be in a format 
different than the one format built-in to the logging module, and the timestamp 
needed to be in the file at all times.  The logging system included a daemon 
that did the equivalent of tail -f on the logfile and collected log events as 
they were written.

Note: I have written code that implements the features described above.

Additional note: some template formats could cause a problem with deleting the 
oldest backup files.

When the option backupCount is set to a number >= 1, then at rotation time the 
handler will check whether the number of backup files exceeds the specified 
count, and will delete the oldest files to reduce the number of backup files to 
exactly the backupCount number.

The oldest files are found by sorting the filenames; the presumption is that 
the archival filenames will sort with the oldest files first.  All the built-in 
templates produce filenames where this presumption is correct.  A foolish user 
could specify a timestamp format where month appears before date, or hour 
appears before month, or any other template that does not follow this ordering: 
year/month/date/hour/minutes/seconds

We could also add a feature where, when the template is specified and 
backupCount is specified, the handler will check that the template follows the 
ordering so that the oldest files do sort first, and raise an exception if the 
template doesn't follow the ordering.  Alternatively, we can add a note in the 
documentation warning of this issue.

--
components: Library (Lib)
messages: 316573
nosy: steveha, vinay.sajip
priority: normal
severity: normal
status: open
title: [logging] template for filename timestamps
type: enhancement
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue33506>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33508] [logging] allow %p code to put PID into log filename

2018-05-14 Thread Steve R. Hastings

New submission from Steve R. Hastings :

Python logging is not multi-process safe.  When a Python program has multiple 
processes, one way to log safely would be to put the process ID number into the 
filename of the log file, giving each process its own log file.

It would be convenient if a %p format code would be expanded to the process ID 
number when the logging system opens the log file.

--
components: Library (Lib)
messages: 316576
nosy: steveha, vinay.sajip
priority: normal
severity: normal
status: open
title: [logging] allow %p code to put PID into log filename
type: enhancement
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue33508>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33510] [logging] add JSON log formatter

2018-05-14 Thread Steve R. Hastings

New submission from Steve R. Hastings :

Many logging aggregation and indexing systems require that log data must be 
written in an easy-to-parse format such as JSON.  A "batteries included" JSON 
log formatter would be a useful enhancement.

I have written code with the following features:

Log events are translated into JSON.  The JSON is formatted without 
indentation, so that one log event will produce one line in the output file.  
Each line is a single JSON object.  Because log files contain many lines and 
JSON logging is usually not read by humans, the JSON separator punctuation are 
set to simply ':' and ',' (no leading or trailing spaces).

The standard fields of a log event turn into key/value pairs in the JSON 
object, using the standard field name as the output JSON key name.  For 
example, a log statement like this: log.info("foo initialized") would result in 
JSON that included: "message": "foo initialized", "levelname": "INFO"

By default, the JSON output has the timestamp as the first key/value pair; 
therefore if the file is sorted, or multiple log files are concatenated and 
then sorted, the logged events will be sorted into elapsed order.  By default, 
the timestamp format is RFC3339: https://tools.ietf.org/html/rfc3339  Also, by 
default, the seconds field will have a fractional part with three digits (i.e. 
millisecond resolution on log event timestamps).

The user can provide a dictionary that will translate key names.  If the user's 
log collection system requires the logging level to have a key name of 
"priority", then by specifying that "levelname" should be mapped to "priority" 
the log event will be output with "priority": "INFO"  This dictionary also 
provides a way to control which logging event fields are written to the logfile 
and in what order.

Taking advantage of a feature already present in the Python logging code: The 
user can provide a dictionary as the only argument after the logging message, 
and it will be handled specially.  For the JSON formatter, the special handling 
is that the key/value pairs from the dictionary will be included in the JSON 
output.  Alternatively, the user can provide a message string that includes % 
templating codes, and specify arguments to be templated in, as is common 
practice in logging.  (This is to be backwards-compatible with code written to 
the current formatters.)

The Python logging code feature mentioned above can be found in 
LogRecord.__init__()  The first thing that init code does is check whether 
there is exactly one argument and it is a non-empty Mapping.

In the case where there are multiple arguments provided and templated into the 
message string, one extra key/value pair is written in the JSON object: the key 
is "args" and the value is a JSON array with the values of the arguments.

Because logging is fundamental, if anything goes wrong it's important to log as 
much as possible.  If any exception is raised during the call to json.dumps() 
that creates an output line, there is fallback code that converts the arguments 
dictionary to a string and logs that string under an identifiable key name such 
as "args_text"  So if someone attempts to log arguments that json.dumps() can't 
handle, something will be written to the logfile even if it's just something 
like "<__main__.Foo object at 0x7f8fe7621da0>"


Here is a concrete example.  The JSON logging formatter is initialized with the 
following field name translation table:

TRANSLATE_FIELD_NAMES = {
"asctime": "@timestamp",
"levelname": "priority",
"message": None,
"process": "pid",
}

The above dictionary means that asctime, levelname, message, and process will 
be written to the output file, in that order.  The output JSON object will have 
key names of, respectively: "@timestamp", priority, message (no change), and 
pid.

Then the following logging call occurs:

 log.info("connecting to server", {"url": server_url, "port": sever_port})



The output written to the log file would be similar to this:

{"@timestamp":"2018-05-14T17:28:04.112-04:00","priority":"INFO","message":"connecting
 to server","pid":32073,"url":"http://127.0.0.1","port":8043}


As noted above, I have already written this code, and it has been in production 
for months at the company where I work.  However, the code can be simplified 
and cleaned up a bit, since it contains Python 2.7 backward compatibility code.

--
components: Library (Lib)
messages: 316597
nosy: steveha, vinay.sajip
priority: normal
severity: normal
status: open
title: [logging] add JSON log formatter
type: enhancement
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue33510>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33506] [logging] template for filename timestamps

2018-05-14 Thread Steve R. Hastings

Steve R. Hastings  added the comment:

> What about [ BaseRotatingHandler.namer ] which allows you to specify your own 
> naming scheme?

I confess that I overlooked that; it was added later than the version of Python 
in which I wrote my original code.

The current Python code still has a small set of predefined file templates, but 
now has a way to specify a callable that can completely override the filename.  
I agree that this can be used to implement any desired filename system, 
although it would be more work than simply specifying the desired template 
codes.

Are you planning to remove the predefined filename templates and produce a more 
functional version of the code where the .namer() function is always used to 
produce a filename, with a set of predefined functions that produce equivalent 
filenames to the built-in templates?

--

___
Python tracker 
<https://bugs.python.org/issue33506>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33510] [logging] add JSON log formatter

2018-05-14 Thread Steve R. Hastings

Steve R. Hastings  added the comment:

The solution recommended in the logging cookbook does not do the same thing as 
I have proposed.

I have proposed a logging handler that emits JSON suitable for ingestion by a 
log collection system.  With the JSON formatter, all log events, no matter 
their source, are written completely in JSON.  This includes log events from 
already-written library functions that have no expectation of JSON output.  
Also the JSON formatter writes timestamps in the now-universally-understood 
RFC3339 format, the easiest date format to parse.

The logging cookbook solution is that the user must explicitly write JSON data 
into the message line of each call to the logging code.  This would make some 
or all of the message field into JSON but does not solve the problem of logging 
in JSON; the other fields of the log file would remain non-JSON.

A company that is using a log collection system might need the logs to be pure 
JSON.  The proposed JSON formatter solves that problem.

P.S. Here is a blog posting on why it is useful to log in pure JSON:

https://journal.paul.querna.org/articles/2011/12/26/log-for-machines-in-json/

--

___
Python tracker 
<https://bugs.python.org/issue33510>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue33506] [logging] template for filename timestamps

2018-05-14 Thread Steve R. Hastings

Steve R. Hastings  added the comment:

I just reviewed the Python 3.6 logging code.  Unless I am mistaken, it still 
has the limitation that when a logging file is active for writing log events, 
that file always has the same filename (self.baseFilename).  Did I overlook 
anything?

At rotation time, the self.namer() function is called, and it could implement 
any desired naming scheme.  However, its only argument is the already templated 
filename.

So if I needed to implement logging with a filename of: foo-mmdd.log at all 
times, how would I get the current file (the open file to which log events are 
being written) to have that pattern of name?

And if I needed to write a self.namer() function to rename to that standard, is 
this the recommended approach?

# for daily rotations, the built-in template is: "%Y-%m-%d"
def namer(self, filename):
# filename will look like: foo--mm-dd.log
year = filename[-14:-10]
month = filename[-9:-7]
day = filename[-6:-4]
base = filename[:-14]
new_filename = base + year + month + day + ".log"
return new_filename  # will look like: foo-mmdd.log

The logging event that triggered the rollover is not passed to the namer() 
function, just the templated default filename.

In my opinion, it is more convenient for the user to simply specify the desired 
format using template codes, such as:

handler = TimedRotatingFileHandler("foo", suffix="-%Y%m%d", when="D")


Also, unless I have overlooked something, using the self.namer() function to 
implement a custom naming scheme completely disables the code that 
automatically deletes the oldest backup files when backupCount is specified.  
The getBackupFilesToDelete() function uses the self.extMatch value (a 
pre-compiled regular expression) to find files to delete; with a custom naming 
scheme, the files will not match the pattern.  Therefore users with a custom 
naming scheme would have to implement some external solution to deleting old 
files after log rotation.

The code I am proposing to donate to Python automatically builds a suitable 
regular expression for the self.extMatch member variable, based on the user's 
specified format string.  I believe this is an advantage for the code I propose 
to donate.

--

___
Python tracker 
<https://bugs.python.org/issue33506>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23958] compile warnings in libffi

2015-04-14 Thread Steve R. Hastings

New submission from Steve R. Hastings:

The normal build should not have any warnings.  The source for libffi included 
some comparisons between signed int and unsigned int, which caused warnings.

The patch changes the signed int variables to unsigned int.

--
components: Build
files: libffi_warning_patch.txt
messages: 241011
nosy: steveha
priority: normal
severity: normal
status: open
title: compile warnings in libffi
type: behavior
versions: Python 3.5
Added file: http://bugs.python.org/file39017/libffi_warning_patch.txt

___
Python tracker 
<http://bugs.python.org/issue23958>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com