mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-06-20 16:54:31 +03:00
Merge pull request #685 from EDCD/enhancement/logging-rotating-archive
Enhancement/logging rotating archive
This commit is contained in:
commit
05971ab4c3
78
EDMC.py
78
EDMC.py
@ -5,41 +5,39 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import sys
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from os.path import getmtime, join
|
||||||
|
from time import sleep, time
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
import collate
|
||||||
|
import commodity
|
||||||
|
import companion
|
||||||
|
import eddn
|
||||||
|
import EDMCLogging
|
||||||
|
import edshipyard
|
||||||
|
import l10n
|
||||||
|
import loadout
|
||||||
|
import outfitting
|
||||||
|
import shipyard
|
||||||
|
import stats
|
||||||
|
from commodity import COMMODITY_DEFAULT
|
||||||
|
from config import appcmdname, appversion, config
|
||||||
|
from monitor import monitor
|
||||||
|
from update import EDMCVersion, Updater
|
||||||
|
|
||||||
# workaround for https://github.com/EDCD/EDMarketConnector/issues/568
|
# workaround for https://github.com/EDCD/EDMarketConnector/issues/568
|
||||||
os.environ["EDMC_NO_UI"] = "1"
|
os.environ["EDMC_NO_UI"] = "1"
|
||||||
|
|
||||||
from os.path import getmtime, join
|
|
||||||
from time import time, sleep
|
|
||||||
import re
|
|
||||||
|
|
||||||
import l10n
|
|
||||||
l10n.Translations.install_dummy()
|
l10n.Translations.install_dummy()
|
||||||
|
|
||||||
import collate
|
logger = EDMCLogging.Logger(appcmdname).get_logger()
|
||||||
import companion
|
|
||||||
import commodity
|
|
||||||
from commodity import COMMODITY_DEFAULT
|
|
||||||
import outfitting
|
|
||||||
import loadout
|
|
||||||
import edshipyard
|
|
||||||
import shipyard
|
|
||||||
import stats
|
|
||||||
from config import appname, appcmdname, appversion, config
|
|
||||||
from update import Updater, EDMCVersion
|
|
||||||
from monitor import monitor
|
|
||||||
|
|
||||||
import EDMCLogging
|
|
||||||
import logging
|
|
||||||
logger = EDMCLogging.Logger(appname).get_logger()
|
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
sys.path.append(config.internal_plugin_dir)
|
sys.path.append(config.internal_plugin_dir)
|
||||||
import eddn
|
|
||||||
|
|
||||||
|
|
||||||
SERVER_RETRY = 5 # retry pause for Companion servers [s]
|
SERVER_RETRY = 5 # retry pause for Companion servers [s]
|
||||||
EXIT_SUCCESS, EXIT_SERVER, EXIT_CREDENTIALS, EXIT_VERIFICATION, EXIT_LAGGING, EXIT_SYS_ERR, EXIT_ARGS = range(7)
|
EXIT_SUCCESS, EXIT_SERVER, EXIT_CREDENTIALS, EXIT_VERIFICATION, EXIT_LAGGING, EXIT_SYS_ERR, EXIT_ARGS = range(7)
|
||||||
@ -78,7 +76,7 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument('-v', '--version', help='print program version and exit', action='store_const', const=True)
|
parser.add_argument('-v', '--version', help='print program version and exit', action='store_const', const=True)
|
||||||
parser.add_argument('--loglevel', metavar='loglevel', help='Set the logging loglevel to one of: CRITICAL, ERROR, WARNING, INFO, DEBUG')
|
parser.add_argument('--loglevel', metavar='loglevel', help='Set the logging loglevel to one of: CRITICAL, ERROR, WARNING, INFO, DEBUG') # noqa: E501
|
||||||
parser.add_argument('-a', metavar='FILE', help='write ship loadout to FILE in Companion API json format')
|
parser.add_argument('-a', metavar='FILE', help='write ship loadout to FILE in Companion API json format')
|
||||||
parser.add_argument('-e', metavar='FILE', help='write ship loadout to FILE in E:D Shipyard plain text format')
|
parser.add_argument('-e', metavar='FILE', help='write ship loadout to FILE in E:D Shipyard plain text format')
|
||||||
parser.add_argument('-l', metavar='FILE', help='write ship locations to FILE in CSV format')
|
parser.add_argument('-l', metavar='FILE', help='write ship locations to FILE in CSV format')
|
||||||
@ -99,7 +97,8 @@ def main():
|
|||||||
print(f'{appversion} ({newversion.title!r} is available)')
|
print(f'{appversion} ({newversion.title!r} is available)')
|
||||||
else:
|
else:
|
||||||
print(appversion)
|
print(appversion)
|
||||||
sys.exit(EXIT_SUCCESS)
|
|
||||||
|
return
|
||||||
|
|
||||||
if args.loglevel:
|
if args.loglevel:
|
||||||
if args.loglevel not in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'):
|
if args.loglevel not in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'):
|
||||||
@ -107,6 +106,8 @@ def main():
|
|||||||
sys.exit(EXIT_ARGS)
|
sys.exit(EXIT_ARGS)
|
||||||
logger.setLevel(args.loglevel)
|
logger.setLevel(args.loglevel)
|
||||||
|
|
||||||
|
logger.debug('Startup')
|
||||||
|
|
||||||
if args.j:
|
if args.j:
|
||||||
logger.debug('Import and collate from JSON dump')
|
logger.debug('Import and collate from JSON dump')
|
||||||
# Import and collate from JSON dump
|
# Import and collate from JSON dump
|
||||||
@ -119,7 +120,8 @@ def main():
|
|||||||
try:
|
try:
|
||||||
logdir = config.get('journaldir') or config.default_journal_dir
|
logdir = config.get('journaldir') or config.default_journal_dir
|
||||||
logger.debug(f'logdir = "{logdir}"')
|
logger.debug(f'logdir = "{logdir}"')
|
||||||
logfiles = sorted((x for x in os.listdir(logdir) if JOURNAL_RE.search(x)), key=lambda x: x.split('.')[1:])
|
logfiles = sorted((x for x in os.listdir(logdir) if JOURNAL_RE.search(x)),
|
||||||
|
key=lambda x: x.split('.')[1:])
|
||||||
|
|
||||||
logfile = join(logdir, logfiles[-1])
|
logfile = join(logdir, logfiles[-1])
|
||||||
|
|
||||||
@ -188,7 +190,7 @@ def main():
|
|||||||
pass # Skip further validation
|
pass # Skip further validation
|
||||||
|
|
||||||
elif data['commander']['name'] != monitor.cmdr:
|
elif data['commander']['name'] != monitor.cmdr:
|
||||||
logger.error(f'Commander "{data["commander"]["name"]}" from CAPI doesn\'t match "{monitor.cmdr}" from Journal')
|
logger.error(f'Commander "{data["commander"]["name"]}" from CAPI doesn\'t match "{monitor.cmdr}" from Journal') # noqa: E501
|
||||||
sys.exit(EXIT_CREDENTIALS)
|
sys.exit(EXIT_CREDENTIALS)
|
||||||
|
|
||||||
elif data['lastSystem']['name'] != monitor.system or \
|
elif data['lastSystem']['name'] != monitor.system or \
|
||||||
@ -196,7 +198,7 @@ def main():
|
|||||||
data['ship']['id'] != monitor.state['ShipID'] or \
|
data['ship']['id'] != monitor.state['ShipID'] or \
|
||||||
data['ship']['name'].lower() != monitor.state['ShipType']:
|
data['ship']['name'].lower() != monitor.state['ShipType']:
|
||||||
|
|
||||||
logger.error('Mismatch(es) between CAPI and Journal for at least one of: StarSystem, Last Star Port, Ship ID or Ship Name/Type')
|
logger.error('Mismatch(es) between CAPI and Journal for at least one of: StarSystem, Last Star Port, Ship ID or Ship Name/Type') # noqa: E501
|
||||||
sys.exit(EXIT_LAGGING)
|
sys.exit(EXIT_LAGGING)
|
||||||
|
|
||||||
# stuff we can do when not docked
|
# stuff we can do when not docked
|
||||||
@ -234,24 +236,24 @@ def main():
|
|||||||
if (args.m or args.o or args.s or args.n or args.j):
|
if (args.m or args.o or args.s or args.n or args.j):
|
||||||
if not data['commander'].get('docked'):
|
if not data['commander'].get('docked'):
|
||||||
logger.error("Can't use -m, -o, -s, -n or -j because you're not currently docked!")
|
logger.error("Can't use -m, -o, -s, -n or -j because you're not currently docked!")
|
||||||
sys.exit(EXIT_SUCCESS)
|
return
|
||||||
|
|
||||||
elif not deep_get(data, 'lastStarport', 'name'):
|
elif not deep_get(data, 'lastStarport', 'name'):
|
||||||
logger.error(f"No data['lastStarport']['name'] from CAPI")
|
logger.error("No data['lastStarport']['name'] from CAPI")
|
||||||
sys.exit(EXIT_LAGGING)
|
sys.exit(EXIT_LAGGING)
|
||||||
|
|
||||||
# Ignore possibly missing shipyard info
|
# Ignore possibly missing shipyard info
|
||||||
elif not data['lastStarport'].get('commodities') or data['lastStarport'].get('modules'):
|
elif not data['lastStarport'].get('commodities') or data['lastStarport'].get('modules'):
|
||||||
logger.error("No commodities or outfitting (modules) in CAPI data")
|
logger.error("No commodities or outfitting (modules) in CAPI data")
|
||||||
sys.exit(EXIT_SUCCESS)
|
return
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sys.exit(EXIT_SUCCESS)
|
return
|
||||||
|
|
||||||
# Finally - the data looks sane and we're docked at a station
|
# Finally - the data looks sane and we're docked at a station
|
||||||
|
|
||||||
if args.j:
|
if args.j:
|
||||||
logger.debug(f'Importing data from the CAPI return...')
|
logger.debug('Importing data from the CAPI return...')
|
||||||
# Collate from JSON dump
|
# Collate from JSON dump
|
||||||
collate.addcommodities(data)
|
collate.addcommodities(data)
|
||||||
collate.addmodules(data)
|
collate.addmodules(data)
|
||||||
@ -307,10 +309,8 @@ def main():
|
|||||||
eddn_sender.export_outfitting(data, monitor.is_beta)
|
eddn_sender.export_outfitting(data, monitor.is_beta)
|
||||||
eddn_sender.export_shipyard(data, monitor.is_beta)
|
eddn_sender.export_shipyard(data, monitor.is_beta)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.exception(f'Failed to send data to EDDN')
|
logger.exception('Failed to send data to EDDN')
|
||||||
|
|
||||||
sys.exit(EXIT_SUCCESS)
|
|
||||||
|
|
||||||
except companion.ServerError:
|
except companion.ServerError:
|
||||||
logger.error('Frontier CAPI Server returned an error')
|
logger.error('Frontier CAPI Server returned an error')
|
||||||
@ -327,3 +327,5 @@ def main():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
logger.debug('Exiting')
|
||||||
|
sys.exit(EXIT_SUCCESS)
|
||||||
|
@ -7,14 +7,16 @@ members on the logging.LogRecord instance for use in logging.Formatter()
|
|||||||
strings.
|
strings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# So that any warning about accessing a protected member is only in one place.
|
|
||||||
from sys import _getframe as getframe
|
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
|
import logging.handlers
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import tempfile
|
||||||
|
# So that any warning about accessing a protected member is only in one place.
|
||||||
|
from sys import _getframe as getframe
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from config import config
|
from config import appname, config
|
||||||
|
|
||||||
# TODO: Tests:
|
# TODO: Tests:
|
||||||
#
|
#
|
||||||
@ -39,7 +41,7 @@ from config import config
|
|||||||
#
|
#
|
||||||
# 14. Call from *package*
|
# 14. Call from *package*
|
||||||
|
|
||||||
_default_loglevel = logging.DEBUG
|
_default_loglevel = logging.INFO
|
||||||
|
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
@ -69,8 +71,9 @@ class Logger:
|
|||||||
self.logger_filter = EDMCContextFilter()
|
self.logger_filter = EDMCContextFilter()
|
||||||
self.logger.addFilter(self.logger_filter)
|
self.logger.addFilter(self.logger_filter)
|
||||||
|
|
||||||
|
# Our basic channel handling stdout
|
||||||
self.logger_channel = logging.StreamHandler()
|
self.logger_channel = logging.StreamHandler()
|
||||||
self.logger_channel.setLevel(loglevel)
|
# Do *NOT* set here, want logger's level to work: self.logger_channel.setLevel(loglevel)
|
||||||
|
|
||||||
self.logger_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s.%(qualname)s:%(lineno)d: %(message)s') # noqa: E501
|
self.logger_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s.%(qualname)s:%(lineno)d: %(message)s') # noqa: E501
|
||||||
self.logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S'
|
self.logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S'
|
||||||
@ -79,6 +82,26 @@ class Logger:
|
|||||||
self.logger_channel.setFormatter(self.logger_formatter)
|
self.logger_channel.setFormatter(self.logger_formatter)
|
||||||
self.logger.addHandler(self.logger_channel)
|
self.logger.addHandler(self.logger_channel)
|
||||||
|
|
||||||
|
# Rotating Handler in sub-directory
|
||||||
|
# We want the files in %TEMP%\{appname}\ as {logger_name}.log and rotated versions
|
||||||
|
# This is {logger_name} so that EDMC.py logs to a different file.
|
||||||
|
logfile_rotating = pathlib.Path(tempfile.gettempdir())
|
||||||
|
logfile_rotating = logfile_rotating / f'{appname}'
|
||||||
|
logfile_rotating.mkdir(exist_ok=True)
|
||||||
|
logfile_rotating = logfile_rotating / f'{logger_name}.log'
|
||||||
|
|
||||||
|
self.logger_channel_rotating = logging.handlers.RotatingFileHandler(
|
||||||
|
logfile_rotating,
|
||||||
|
mode='a',
|
||||||
|
maxBytes=1024 * 1024, # 1MiB
|
||||||
|
backupCount=10,
|
||||||
|
encoding='utf-8',
|
||||||
|
delay=False
|
||||||
|
)
|
||||||
|
# Do *NOT* set here, want logger's level to work: self.logger_channel_rotating.setLevel(loglevel)
|
||||||
|
self.logger_channel_rotating.setFormatter(self.logger_formatter)
|
||||||
|
self.logger.addHandler(self.logger_channel_rotating)
|
||||||
|
|
||||||
def get_logger(self) -> logging.Logger:
|
def get_logger(self) -> logging.Logger:
|
||||||
"""
|
"""
|
||||||
Obtain the self.logger of the class instance.
|
Obtain the self.logger of the class instance.
|
||||||
|
@ -1031,11 +1031,11 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
enforce_single_instance()
|
enforce_single_instance()
|
||||||
|
|
||||||
logger = EDMCLogging.Logger(appname).get_logger()
|
|
||||||
loglevel = config.get('loglevel')
|
loglevel = config.get('loglevel')
|
||||||
if not loglevel:
|
if not loglevel:
|
||||||
loglevel = logging.INFO
|
loglevel = logging.INFO
|
||||||
logger.setLevel(loglevel)
|
logger = EDMCLogging.Logger(appname, loglevel=loglevel).get_logger()
|
||||||
|
logger.info('Startup')
|
||||||
|
|
||||||
# TODO: unittests in place of these
|
# TODO: unittests in place of these
|
||||||
# logger.debug('Test from __main__')
|
# logger.debug('Test from __main__')
|
||||||
@ -1083,3 +1083,5 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
root.after(0, messagebox_not_py3)
|
root.after(0, messagebox_not_py3)
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
logger.info('Exiting')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user