zephyr_mirror: Fix logging messages to multiple files under /tmp.
Also fixes the fact that certain output was not logged at all. (imported from commit 0e63a9ef4105921ad7cbe3f7565ce7832c5db25e)
This commit is contained in:
parent
9ebfa84385
commit
630b7ae521
|
@ -20,7 +20,7 @@ def fetch_public_streams():
|
||||||
if res.get("result") == "success":
|
if res.get("result") == "success":
|
||||||
streams = res["streams"]
|
streams = res["streams"]
|
||||||
else:
|
else:
|
||||||
logging.error("Error getting public streams:\n%s" % res)
|
logging.error("Error getting public streams:\n%s" % (res,))
|
||||||
return None
|
return None
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Error getting public streams:")
|
logging.exception("Error getting public streams:")
|
||||||
|
|
|
@ -153,19 +153,19 @@ def zephyr_bulk_subscribe(subs):
|
||||||
# retrying the next time the bot checks its subscriptions are
|
# retrying the next time the bot checks its subscriptions are
|
||||||
# up to date.
|
# up to date.
|
||||||
logger.exception("Error subscribing to streams (will retry automatically):")
|
logger.exception("Error subscribing to streams (will retry automatically):")
|
||||||
logging.warning("Streams were: %s" % ([cls for cls, instance, recipient in subs],))
|
logger.warning("Streams were: %s" % ([cls for cls, instance, recipient in subs],))
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
actual_zephyr_subs = [cls for (cls, _, _) in zephyr._z.getSubscriptions()]
|
actual_zephyr_subs = [cls for (cls, _, _) in zephyr._z.getSubscriptions()]
|
||||||
except IOError:
|
except IOError:
|
||||||
logging.exception("Error getting current Zephyr subscriptions")
|
logger.exception("Error getting current Zephyr subscriptions")
|
||||||
# Don't add anything to current_zephyr_subs so that we'll
|
# Don't add anything to current_zephyr_subs so that we'll
|
||||||
# retry the next time we check for streams to subscribe to
|
# retry the next time we check for streams to subscribe to
|
||||||
# (within 15 seconds).
|
# (within 15 seconds).
|
||||||
return
|
return
|
||||||
for (cls, instance, recipient) in subs:
|
for (cls, instance, recipient) in subs:
|
||||||
if cls not in actual_zephyr_subs:
|
if cls not in actual_zephyr_subs:
|
||||||
logging.error("Zephyr failed to subscribe us to %s; will retry" % (cls,))
|
logger.error("Zephyr failed to subscribe us to %s; will retry" % (cls,))
|
||||||
try:
|
try:
|
||||||
# We'll retry automatically when we next check for
|
# We'll retry automatically when we next check for
|
||||||
# streams to subscribe to (within 15 seconds), but
|
# streams to subscribe to (within 15 seconds), but
|
||||||
|
@ -211,13 +211,13 @@ def maybe_restart_mirroring_script():
|
||||||
if child_pid is not None:
|
if child_pid is not None:
|
||||||
os.kill(child_pid, signal.SIGTERM)
|
os.kill(child_pid, signal.SIGTERM)
|
||||||
except OSError:
|
except OSError:
|
||||||
# We don't care if the child process no longer exists, so just print the error
|
# We don't care if the child process no longer exists, so just log the error
|
||||||
logging.exception("")
|
logger.exception("")
|
||||||
try:
|
try:
|
||||||
zephyr._z.cancelSubs()
|
zephyr._z.cancelSubs()
|
||||||
except IOError:
|
except IOError:
|
||||||
# We don't care whether we failed to cancel subs properly, but we should log it
|
# We don't care whether we failed to cancel subs properly, but we should log it
|
||||||
logging.exception("")
|
logger.exception("")
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
os.execvp(os.path.join(options.root_path, "user_root", "zephyr_mirror_backend.py"), sys.argv)
|
os.execvp(os.path.join(options.root_path, "user_root", "zephyr_mirror_backend.py"), sys.argv)
|
||||||
|
@ -245,7 +245,7 @@ def process_loop(log):
|
||||||
try:
|
try:
|
||||||
maybe_restart_mirroring_script()
|
maybe_restart_mirroring_script()
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Error checking whether restart is required:")
|
logger.exception("Error checking whether restart is required:")
|
||||||
|
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
sleep_count += sleep_time
|
sleep_count += sleep_time
|
||||||
|
@ -256,7 +256,7 @@ def process_loop(log):
|
||||||
try:
|
try:
|
||||||
update_subscriptions()
|
update_subscriptions()
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Error updating subscriptions from Humbug:")
|
logger.exception("Error updating subscriptions from Humbug:")
|
||||||
|
|
||||||
def parse_zephyr_body(zephyr_data):
|
def parse_zephyr_body(zephyr_data):
|
||||||
try:
|
try:
|
||||||
|
@ -346,7 +346,7 @@ def process_notice(notice, log):
|
||||||
if res.get("result") != "success":
|
if res.get("result") != "success":
|
||||||
logger.error("Error relaying zephyr:\n%s\n%s" % (zeph, res))
|
logger.error("Error relaying zephyr:\n%s\n%s" % (zeph, res))
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Error relaying zephyr:")
|
logger.exception("Error relaying zephyr:")
|
||||||
finally:
|
finally:
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ def zephyr_subscribe_autoretry(sub):
|
||||||
zephyr.Subscriptions().add(sub)
|
zephyr.Subscriptions().add(sub)
|
||||||
return
|
return
|
||||||
except IOError:
|
except IOError:
|
||||||
# Probably a SERVNAK from the zephyr server, but print the
|
# Probably a SERVNAK from the zephyr server, but log the
|
||||||
# traceback just in case it's something else
|
# traceback just in case it's something else
|
||||||
logger.exception("Error subscribing to personals (retrying). Traceback:")
|
logger.exception("Error subscribing to personals (retrying). Traceback:")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
@ -419,15 +419,15 @@ def send_zephyr(zwrite_args, content):
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdout, stderr = p.communicate(input=content.encode("utf-8"))
|
stdout, stderr = p.communicate(input=content.encode("utf-8"))
|
||||||
if p.returncode:
|
if p.returncode:
|
||||||
logging.error("zwrite command '%s' failed with return code %d:" % (
|
logger.error("zwrite command '%s' failed with return code %d:" % (
|
||||||
" ".join(zwrite_args), p.returncode,))
|
" ".join(zwrite_args), p.returncode,))
|
||||||
if stdout:
|
if stdout:
|
||||||
logging.info("stdout: " + stdout)
|
logger.info("stdout: " + stdout)
|
||||||
elif stderr:
|
elif stderr:
|
||||||
logging.warning("zwrite command '%s' printed the following warning:" % (
|
logger.warning("zwrite command '%s' printed the following warning:" % (
|
||||||
" ".join(zwrite_args),))
|
" ".join(zwrite_args),))
|
||||||
if stderr:
|
if stderr:
|
||||||
logging.warning("stderr: " + stderr)
|
logger.warning("stderr: " + stderr)
|
||||||
return (p.returncode, stderr)
|
return (p.returncode, stderr)
|
||||||
|
|
||||||
def send_authed_zephyr(zwrite_args, content):
|
def send_authed_zephyr(zwrite_args, content):
|
||||||
|
@ -597,7 +597,7 @@ def add_humbug_subscriptions(verbose):
|
||||||
zephyr_subscriptions.add(instance)
|
zephyr_subscriptions.add(instance)
|
||||||
continue
|
continue
|
||||||
elif cls.lower() == "mail" and instance.lower() == "inbox":
|
elif cls.lower() == "mail" and instance.lower() == "inbox":
|
||||||
# We forward mail zephyrs, so no need to print a warning.
|
# We forward mail zephyrs, so no need to log a warning.
|
||||||
continue
|
continue
|
||||||
elif len(cls) > 30:
|
elif len(cls) > 30:
|
||||||
skipped.add((cls, instance, recipient, "Class longer than 30 characters"))
|
skipped.add((cls, instance, recipient, "Class longer than 30 characters"))
|
||||||
|
@ -613,24 +613,20 @@ def add_humbug_subscriptions(verbose):
|
||||||
if len(zephyr_subscriptions) != 0:
|
if len(zephyr_subscriptions) != 0:
|
||||||
res = humbug_client.add_subscriptions(list(zephyr_subscriptions))
|
res = humbug_client.add_subscriptions(list(zephyr_subscriptions))
|
||||||
if res.get("result") != "success":
|
if res.get("result") != "success":
|
||||||
print "Error subscribing to streams:"
|
logger.error("Error subscribing to streams:\n%s" % (res["msg"],))
|
||||||
print res["msg"]
|
|
||||||
return
|
return
|
||||||
|
|
||||||
already = res.get("already_subscribed")
|
already = res.get("already_subscribed")
|
||||||
new = res.get("subscribed")
|
new = res.get("subscribed")
|
||||||
if verbose:
|
if verbose:
|
||||||
if already is not None and len(already) > 0:
|
if already is not None and len(already) > 0:
|
||||||
print
|
logger.info("\nAlready subscribed to: %s" % (", ".join(already),))
|
||||||
print "Already subscribed to:", ", ".join(already)
|
|
||||||
if new is not None and len(new) > 0:
|
if new is not None and len(new) > 0:
|
||||||
print
|
logger.info("\nSuccessfully subscribed to: %s" % (", ".join(new),))
|
||||||
print "Successfully subscribed to:", ", ".join(new)
|
|
||||||
|
|
||||||
if len(skipped) > 0:
|
if len(skipped) > 0:
|
||||||
if verbose:
|
if verbose:
|
||||||
print
|
logger.info("\n" + "\n".join(textwrap.wrap("""\
|
||||||
print "\n".join(textwrap.wrap("""\
|
|
||||||
You have some lines in ~/.zephyr.subs that could not be
|
You have some lines in ~/.zephyr.subs that could not be
|
||||||
synced to your Humbug subscriptions because they do not
|
synced to your Humbug subscriptions because they do not
|
||||||
use "*" as both the instance and recipient and not one of
|
use "*" as both the instance and recipient and not one of
|
||||||
|
@ -639,27 +635,23 @@ Humbug has a mechanism for forwarding. Humbug does not
|
||||||
allow subscribing to only some subjects on a Humbug
|
allow subscribing to only some subjects on a Humbug
|
||||||
stream, so this tool has not created a corresponding
|
stream, so this tool has not created a corresponding
|
||||||
Humbug subscription to these lines in ~/.zephyr.subs:
|
Humbug subscription to these lines in ~/.zephyr.subs:
|
||||||
"""))
|
""")) + "\n")
|
||||||
print
|
|
||||||
|
|
||||||
for (cls, instance, recipient, reason) in skipped:
|
for (cls, instance, recipient, reason) in skipped:
|
||||||
if verbose:
|
if verbose:
|
||||||
if reason != "":
|
if reason != "":
|
||||||
print " [%s,%s,%s] (%s)" % (cls, instance, recipient, reason)
|
logger.info(" [%s,%s,%s] (%s)" % (cls, instance, recipient, reason))
|
||||||
else:
|
else:
|
||||||
print " [%s,%s,%s]" % (cls, instance, recipient, reason)
|
logger.info(" [%s,%s,%s]" % (cls, instance, recipient))
|
||||||
if len(skipped) > 0:
|
if len(skipped) > 0:
|
||||||
if verbose:
|
if verbose:
|
||||||
print
|
logger.info("\n" + "\n".join(textwrap.wrap("""\
|
||||||
print "\n".join(textwrap.wrap("""\
|
|
||||||
If you wish to be subscribed to any Humbug streams related
|
If you wish to be subscribed to any Humbug streams related
|
||||||
to these .zephyrs.subs lines, please do so via the Humbug
|
to these .zephyrs.subs lines, please do so via the Humbug
|
||||||
web interface.
|
web interface.
|
||||||
"""))
|
""")) + "\n")
|
||||||
print
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print
|
logger.info("\nIMPORTANT: Please reload the Humbug app for these changes to take effect.\n")
|
||||||
print "IMPORTANT: Please reload the Humbug app for these changes to take effect."
|
|
||||||
|
|
||||||
def valid_stream_name(name):
|
def valid_stream_name(name):
|
||||||
return name != ""
|
return name != ""
|
||||||
|
@ -669,7 +661,7 @@ def parse_zephyr_subs(verbose=False):
|
||||||
subs_file = os.path.join(os.environ["HOME"], ".zephyr.subs")
|
subs_file = os.path.join(os.environ["HOME"], ".zephyr.subs")
|
||||||
if not os.path.exists(subs_file):
|
if not os.path.exists(subs_file):
|
||||||
if verbose:
|
if verbose:
|
||||||
print >>sys.stderr, "Couldn't find ~/.zephyr.subs!"
|
logger.error("Couldn't find ~/.zephyr.subs!")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
for line in file(subs_file, "r").readlines():
|
for line in file(subs_file, "r").readlines():
|
||||||
|
@ -683,11 +675,11 @@ def parse_zephyr_subs(verbose=False):
|
||||||
recipient = recipient.replace("%me%", options.user)
|
recipient = recipient.replace("%me%", options.user)
|
||||||
if not valid_stream_name(cls):
|
if not valid_stream_name(cls):
|
||||||
if verbose:
|
if verbose:
|
||||||
print >>sys.stderr, "Skipping subscription to unsupported class name: [%s]" % (line,)
|
logger.error("Skipping subscription to unsupported class name: [%s]" % (line,))
|
||||||
continue
|
continue
|
||||||
except Exception:
|
except Exception:
|
||||||
if verbose:
|
if verbose:
|
||||||
print >>sys.stderr, "Couldn't parse ~/.zephyr.subs line: [%s]" % (line,)
|
logger.error("Couldn't parse ~/.zephyr.subs line: [%s]" % (line,))
|
||||||
continue
|
continue
|
||||||
zephyr_subscriptions.add((cls.strip(), instance.strip(), recipient.strip()))
|
zephyr_subscriptions.add((cls.strip(), instance.strip(), recipient.strip()))
|
||||||
return zephyr_subscriptions
|
return zephyr_subscriptions
|
||||||
|
@ -705,7 +697,7 @@ def fetch_fullname(username):
|
||||||
|
|
||||||
return username
|
return username
|
||||||
|
|
||||||
def configure_logger(direction_name):
|
def open_logger():
|
||||||
if options.forward_class_messages:
|
if options.forward_class_messages:
|
||||||
if options.test_mode:
|
if options.test_mode:
|
||||||
log_file = "/home/humbug/test-mirror-log"
|
log_file = "/home/humbug/test-mirror-log"
|
||||||
|
@ -719,7 +711,7 @@ def configure_logger(direction_name):
|
||||||
# reopen it anyway.
|
# reopen it anyway.
|
||||||
f.close()
|
f.close()
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
log_format = "%(asctime)s " + direction_name + ": %(message)s"
|
log_format = "%(asctime)s <initial>: %(message)s"
|
||||||
formatter = logging.Formatter(log_format)
|
formatter = logging.Formatter(log_format)
|
||||||
logging.basicConfig(format=log_format)
|
logging.basicConfig(format=log_format)
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
@ -728,6 +720,20 @@ def configure_logger(direction_name):
|
||||||
logger.addHandler(file_handler)
|
logger.addHandler(file_handler)
|
||||||
return logger
|
return logger
|
||||||
|
|
||||||
|
def configure_logger(logger, direction_name):
|
||||||
|
if direction_name is None:
|
||||||
|
log_format = "%(message)s"
|
||||||
|
else:
|
||||||
|
log_format = "%(asctime)s [" + direction_name + "] %(message)s"
|
||||||
|
formatter = logging.Formatter(log_format)
|
||||||
|
|
||||||
|
# Replace the formatters for the file and stdout loggers
|
||||||
|
for handler in logger.handlers:
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
root_logger = logging.getLogger()
|
||||||
|
for handler in root_logger.handlers:
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
parser.add_option('--forward-class-messages',
|
parser.add_option('--forward-class-messages',
|
||||||
|
@ -791,7 +797,7 @@ def die_gracefully(signal, frame):
|
||||||
zephyr._z.cancelSubs()
|
zephyr._z.cancelSubs()
|
||||||
except IOError:
|
except IOError:
|
||||||
# We don't care whether we failed to cancel subs properly, but we should log it
|
# We don't care whether we failed to cancel subs properly, but we should log it
|
||||||
logging.exception("")
|
logger.exception("")
|
||||||
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -808,6 +814,9 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
(options, args) = parse_args()
|
(options, args) = parse_args()
|
||||||
|
|
||||||
|
logger = open_logger()
|
||||||
|
configure_logger(logger, "parent")
|
||||||
|
|
||||||
# The 'api' directory needs to go first, so that 'import humbug' won't pick
|
# The 'api' directory needs to go first, so that 'import humbug' won't pick
|
||||||
# up some other directory named 'humbug'.
|
# up some other directory named 'humbug'.
|
||||||
pyzephyr_lib_path = "python-zephyr/build/lib.linux-" + os.uname()[4] + "-2.6/"
|
pyzephyr_lib_path = "python-zephyr/build/lib.linux-" + os.uname()[4] + "-2.6/"
|
||||||
|
@ -823,10 +832,10 @@ if __name__ == "__main__":
|
||||||
api_key = os.environ.get("HUMBUG_API_KEY")
|
api_key = os.environ.get("HUMBUG_API_KEY")
|
||||||
else:
|
else:
|
||||||
if not os.path.exists(options.api_key_file):
|
if not os.path.exists(options.api_key_file):
|
||||||
print "\n".join(textwrap.wrap("""\
|
logger.error("\n" + "\n".join(textwrap.wrap("""\
|
||||||
Could not find API key file.
|
Could not find API key file.
|
||||||
You need to either place your api key file at %s,
|
You need to either place your api key file at %s,
|
||||||
or specify the --api-key-file option.""" % (options.api_key_file,)))
|
or specify the --api-key-file option.""" % (options.api_key_file,))))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
api_key = file(options.api_key_file).read().strip()
|
api_key = file(options.api_key_file).read().strip()
|
||||||
# Store the API key in the environment so that our children
|
# Store the API key in the environment so that our children
|
||||||
|
@ -845,7 +854,8 @@ or specify the --api-key-file option.""" % (options.api_key_file,)))
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
if options.sync_subscriptions:
|
if options.sync_subscriptions:
|
||||||
print "Syncing your ~/.zephyr.subs to your Humbug Subscriptions!"
|
configure_logger(logger, None) # make the output cleaner
|
||||||
|
logger.info("Syncing your ~/.zephyr.subs to your Humbug Subscriptions!")
|
||||||
add_humbug_subscriptions(True)
|
add_humbug_subscriptions(True)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
@ -863,12 +873,12 @@ or specify the --api-key-file option.""" % (options.api_key_file,)))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Another copy of zephyr_mirror.py! Kill it.
|
# Another copy of zephyr_mirror.py! Kill it.
|
||||||
print "Killing duplicate zephyr_mirror process %s" % (pid,)
|
logger.info("Killing duplicate zephyr_mirror process %s" % (pid,))
|
||||||
try:
|
try:
|
||||||
os.kill(pid, signal.SIGINT)
|
os.kill(pid, signal.SIGINT)
|
||||||
except OSError:
|
except OSError:
|
||||||
# We don't care if the target process no longer exists, so just print the error
|
# We don't care if the target process no longer exists, so just log the error
|
||||||
traceback.print_exc()
|
logger.exception("")
|
||||||
|
|
||||||
if options.shard is not None and set(options.shard) != set("a"):
|
if options.shard is not None and set(options.shard) != set("a"):
|
||||||
# The shard that is all "a"s is the one that handles personals
|
# The shard that is all "a"s is the one that handles personals
|
||||||
|
@ -881,7 +891,7 @@ or specify the --api-key-file option.""" % (options.api_key_file,)))
|
||||||
if child_pid == 0:
|
if child_pid == 0:
|
||||||
CURRENT_STATE = States.HumbugToZephyr
|
CURRENT_STATE = States.HumbugToZephyr
|
||||||
# Run the humbug => zephyr mirror in the child
|
# Run the humbug => zephyr mirror in the child
|
||||||
logger = configure_logger("humbug=>zephyr")
|
configure_logger(logger, "humbug=>zephyr")
|
||||||
zsig_fullname = fetch_fullname(options.user)
|
zsig_fullname = fetch_fullname(options.user)
|
||||||
humbug_to_zephyr(options)
|
humbug_to_zephyr(options)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -897,12 +907,12 @@ or specify the --api-key-file option.""" % (options.api_key_file,)))
|
||||||
zephyr.init()
|
zephyr.init()
|
||||||
break
|
break
|
||||||
except IOError:
|
except IOError:
|
||||||
traceback.print_exc()
|
logger.exception("")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
logger_name = "zephyr=>humbug"
|
logger_name = "zephyr=>humbug"
|
||||||
if options.shard is not None:
|
if options.shard is not None:
|
||||||
logger_name += "(%s)" % (options.shard,)
|
logger_name += "(%s)" % (options.shard,)
|
||||||
logger = configure_logger(logger_name)
|
configure_logger(logger, logger_name)
|
||||||
# Have the kernel reap children for when we fork off processes to send Humbugs
|
# Have the kernel reap children for when we fork off processes to send Humbugs
|
||||||
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
|
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
|
||||||
zephyr_to_humbug(options)
|
zephyr_to_humbug(options)
|
||||||
|
|
Loading…
Reference in a new issue