Skip to content

Commit

Permalink
push and pop TODOs, mostly around warning, which now exists on the co…
Browse files Browse the repository at this point in the history
…ntext through the new note() interface
  • Loading branch information
mahmoud committed Mar 5, 2016
1 parent e1f8278 commit b253411
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 70 deletions.
6 changes: 6 additions & 0 deletions TODO.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ helper: get_record_parent(record):
Ideal behavior: Only tell me about completing things unless there is
an inner task or the task is taking a long time (heartbeat-based
flush).


Linty things
------------

* Find all sinks that aren't installed in loggers
12 changes: 8 additions & 4 deletions lithoxyl/actors.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, task, interval=DEFAULT_INTERVAL, **kwargs):
max_interval = kwargs.pop('max_interval', None)
self.max_interval = float(max_interval or interval * 8)
self._daemonize_thread = kwargs.pop('daemonize_thread', True)
self._note = kwargs.pop('note', None)
if kwargs:
raise TypeError('unexpected keyword arguments: %r' % kwargs.keys())

Expand Down Expand Up @@ -87,8 +88,11 @@ def join(self, timeout=None):
self._stopping.clear()
return ret

def log(self, level, name, message):
print level, '-', name, '-', message
def note(self, name, message, *a, **kw):
if self._note:
name = 'actor_' + str(name)
self._note(name, message)
return

def _run(self):
self._run_start_time = time.time()
Expand All @@ -103,8 +107,8 @@ def _run(self):
if not self._daemonize_thread:
raise
except Exception as e:
self.log('critical', 'task_exception',
'%s - task() raised: %r' % (time.time(), e))
self.note('task_exception', '%s - task() raised: %r'
% (time.time(), e))
self.interval = min(self.interval * 2, self.max_interval)
else:
decrement = (self.max_interval - self._orig_interval) / 8
Expand Down
26 changes: 26 additions & 0 deletions lithoxyl/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def set_context(context):
return context


def note(name, message, *a, **kw):
return get_context().note(name, message, *a, **kw)


class LithoxylContext(object):
def __init__(self, **kwargs):
self.loggers = []
Expand All @@ -36,6 +40,28 @@ def __init__(self, **kwargs):
self.async_timeout = DEFAULT_JOIN_TIMEOUT
self._async_atexit_registered = False

self.note_handlers = []

def note(self, name, message, *a, **kw):
"""Lithoxyl can't use itself internally. This is a hook for recording
all of those error conditions that need to be robustly
ignored, such as if a user's message doesn't format correctly
at runtime.
"""
if not self.note_handlers:
return
# call_level = kw.pop('call_level', None)
callpoint = None
# if call_level:
# callpoint = None # TODO: extract callpoint info
try:
message = message % a
except Exception:
pass
for nh in self.note_handlers:
nh(name, message, callpoint=callpoint)
return

def enable_async(self, **kwargs):
update_loggers = kwargs.pop('update_loggers', True)
update_sigterm = kwargs.pop('update_sigterm', True)
Expand Down
63 changes: 14 additions & 49 deletions lithoxyl/emitters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import os
import sys

from context import note

try:
# unix only
from _syslog_emitter import SyslogEmitter
Expand Down Expand Up @@ -47,6 +49,7 @@ def emit_entry(self, record, entry):
on_begin = on_warn = on_complete = emit_entry


# TODO: rename StreamLineEmitter
class StreamEmitter(object):
def __init__(self, stream, encoding=None, **kwargs):
if stream == 'stdout':
Expand All @@ -62,7 +65,6 @@ def __init__(self, stream, encoding=None, **kwargs):
encoding = getattr(stream, 'encoding', None) or 'UTF-8'
errors = kwargs.pop('errors', 'backslashreplace')

# Too late to raise exceptions? Don't think so.
check_encoding_settings(encoding, errors) # raises on error

self.newline = kwargs.pop('newline', None) or os.linesep
Expand All @@ -72,35 +74,30 @@ def __init__(self, stream, encoding=None, **kwargs):
def emit_entry(self, record, entry):
try:
entry = entry.encode(self.encoding, self.errors)
except UnicodeDecodeError:
except UnicodeDecodeError as ude:
# Note that this is a *decode* error, meaning a bytestring
# found its way through and implicit decoding is
# happening.
# TODO: configurable behavior for if bytes manage to find
# their way through?
# found its way through and implicit decoding is happening.
note('emit_encode', 'got %r on %s.emit_entry();'
' expected decoded text, not %r', ude, self, entry)
raise
try:
self.stream.write(entry)
if self.newline:
self.stream.write(self.newline)
self.flush()
except Exception:
# TODO: something maybe
# TODO: built-in logging raises KeyboardInterrupts and
# SystemExits, special handling for everything else.
raise
except Exception as e:
note('stream_emit', 'got %r on %r.emit_entry()', e, self)

on_begin = on_warn = on_complete = emit_entry

def flush(self):
#if callable(getattr(self.stream, 'flush', None)):
# if callable(getattr(self.stream, 'flush', None)):
if self.stream is None:
return
try:
self.stream.flush()
except Exception:
# TODO: warn
pass
except Exception as e:
note('stream_flush', 'got %r on %r.flush()', e, self)

def __repr__(self):
return '<%s stream=%r>' % (self.__class__.__name__, self.stream)
Expand All @@ -120,37 +117,5 @@ def close(self):
try:
self.flush()
self.stream.close()
except Exception:
# TODO: warn
pass


class WatchedFileEmitter(FileEmitter):
def __init__(self, *a, **kw):
# TODO: warn on windows usage
super(WatchedFileEmitter, self).__init__(*a, **kw)
try:
stat = os.stat(self.filepath)
self.dev, self.inode = stat.st_dev, stat.st_ino
except OSError:
# TODO: check errno? prolly not.
self.dev, self.inode = None, None

def emit(self, record, entry):
try:
stat = os.stat(self.filepath)
new_dev, new_inode = stat.st_dev, stat.st_ino
except OSError:
new_dev, new_inode = None, None
is_changed = (new_dev, new_inode) != (self.dev, self.inode)
if is_changed and self.stream is not None:
self.close()
self.stream = open(self.filepath, self.mode)
stat = os.stat(self.filepath)
self.dev, self.inode = stat.st_dev, stat.st_ino
super(WatchedFileEmitter, self).emit(record)


class RotatingFileEmitter(FileEmitter):
def __init__(self, filepath):
pass
except Exception as e:
note('file_close', 'got %r on %r.close()', e, self)
2 changes: 0 additions & 2 deletions lithoxyl/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
"""
# NOTE: docstring table needs slashes double escaped. Also, newline literals "\n" removed.

# TODO: should record_id be combined with logger_id? loggers are not
# ephemeral, but records are; there are chances of id reuse.
# TODO: exc_repr field

import os
Expand Down
17 changes: 8 additions & 9 deletions lithoxyl/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ def flush(self):
for preflush_hook in self.preflush_hooks:
try:
preflush_hook(self)
except Exception:
pass
except Exception as e:
self.context.note('preflush', 'hook %r got exception %r',
preflush_hook, e)
queue = self.record_queue
while queue:
rec_type, rec = queue.popleft()
Expand All @@ -138,7 +139,8 @@ def flush(self):
for comment_hook in self._comment_hooks:
comment_hook(rec)
else:
pass # TODO
self.context.note('flush', 'unknown event type: %r %r',
rec_type, rec)
self.last_flush = time.time()
return

Expand Down Expand Up @@ -187,8 +189,7 @@ def add_sink(self, sink):
comment_hook = getattr(sink, 'on_comment', None)
if callable(comment_hook):
self._comment_hooks.append(comment_hook)


# TODO: also pull flush methods?
self._all_sinks.append(sink)

def on_complete(self, complete_record):
Expand Down Expand Up @@ -226,10 +227,8 @@ def on_exception(self, exc_record, exc_type, exc_obj, exc_tb):
return

def comment(self, message, *a, **kw):
root = self.record_type(logger=self,
level=CRITICAL,
name='comment',
data=kw)
root_type = self.record_type
root = root_type(logger=self, level=CRITICAL, name='comment', data=kw)
cur_time = time.time()
root.begin_record = BeginRecord(root, cur_time, 'comment', ())
root.complete_record = CompleteRecord(root, cur_time,
Expand Down
12 changes: 6 additions & 6 deletions lithoxyl/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

from tbutils import ExceptionInfo, Callpoint

from common import DEBUG, INFO, CRITICAL, to_unicode, get_level
from context import note
from formatters import RecordFormatter
from common import DEBUG, INFO, CRITICAL, to_unicode, get_level


_REC_ID_ITER = itertools.count()
Expand Down Expand Up @@ -84,7 +85,7 @@ def __init__(self, logger, level, name,
frame = sys._getframe(1)
self.callpoint = Callpoint.from_frame(frame)

self.begin_record = None # TODO: may have to make BeginRecord here
self.begin_record = None
self.complete_record = None
# these can go internal and be lazily created through properties
self.warn_records = []
Expand Down Expand Up @@ -227,8 +228,9 @@ def __exit__(self, exc_type, exc_val, exc_tb):
try:
self._exception(exc_type, exc_val, exc_tb,
message=None, fargs=(), data={})
except Exception:
# TODO: something? grasshopper mode maybe.
except Exception as e:
note('record_exit',
'got %r while already handling exception %r', e, exc_val)
pass # TODO: still have to create complete_record
else:
if self.complete_record:
Expand Down Expand Up @@ -299,7 +301,6 @@ def __getitem__(self, key):
def __getattr__(self, name):
return getattr(self.root, name)

# TODO
@property
def message(self):
if self._message:
Expand Down Expand Up @@ -379,7 +380,6 @@ def __init__(self, root, ctime, raw_message, fargs):
class CommentRecord(SubRecord):
status_char = '#'

# TODO
def __init__(self, root, ctime, raw_message, fargs):
self.root = root
self.ctime = ctime
Expand Down

0 comments on commit b253411

Please sign in to comment.