Commit e41e74f8 authored by Vincent Pelletier's avatar Vincent Pelletier

Add support for configuration files.

parent e51ab440
......@@ -161,6 +161,43 @@ without parsing more logs::
apachedex --default foo --state-file save_state.json save_state.2.json
--period day --out index.html
Configuration files
Providing a filename prefixed by "@" puts the content of that file in place of
that argument, recursively. Each file is loaded relative to the containing
directory of referencing file, or current working directory for command line.
- foo/dev.cfg::
- foo/site.cfg::
--default Front-office
# This is a comment
--prefix "+Back office" "/back(/|$|\?)" # This is another comment
--skip-prefix "/baz/ignored(/|$|\?)" --prefix +Something "/baz(/|$|\?)"
- command line::
apachedex --skip-base "/ignored(/|$|\?)" @foo/dev.cfg --out index.html
This is equivalent to::
apachedex --skip-base "/ignored(/|$|\?)" --error-detail
--default Front-office --prefix "+Back office" "/back(/|$|\?)"
--skip-prefix "/baz/ignored(/|$|\?)" --prefix +Something "/baz(/|$|\?)"
--stats --out index.html access.log
Portability note: the use of paths containing directory elements inside
configuration files is discouraged, as it's not portable. This may change
later (ex: deciding that import paths are URLs and applying their rules).
......@@ -44,6 +44,7 @@ import math
import os
import platform
import re
import shlex
import sys
import time
import traceback
......@@ -751,6 +752,49 @@ class AggregateSiteUrl(argparse.Action):
suffix=lambda x: match_suffix(x).group('suffix'))
site_list.append((value, match, action))
class ShlexArgumentParser(argparse.ArgumentParser):
Two objectives in this class:
- use shlex to split config files
- when recursively including files, do it from referer's path instead of
current working directory, to facilitate relative inclusion.
# XXX: I whould like to be able to hook inside _read_args_from_files, but
# it would be dirtier. Instead, declare a private method doing similar
# replacement before handing args to original parse_known_args.
def __read_args_from_files(self, args, cwd):
new_args = []
append = new_args.append
extend = new_args.extend
for arg in args:
if arg[:1] in self.fromfile_prefix_chars:
filepath = arg[1:]
new_cwd = os.path.normpath(os.path.join(
with open(os.path.join(new_cwd, os.path.basename(filepath))
) as in_file:
shlex.split(, comments=True),
except IOError, exc:
return new_args
def parse_known_args(self, args=None, namespace=None):
if args is None:
args = sys.argv[1:]
args = list(args)
args = self.__read_args_from_files(args, os.getcwd())
return super(ShlexArgumentParser, self).parse_known_args(args=args,
def _asMonthString(timestamp):
dt, _ = timestamp.split(' ')
_, month, year = dt.split(':', 1)[0].split('/')
......@@ -1060,8 +1104,8 @@ json.decoder.scanstring = _scanstring
def main():
global abs_file_container
parser = argparse.ArgumentParser(description='Compute Apdex out of '
'apache-style log files')
parser = ShlexArgumentParser(description='Compute Apdex out of '
'apache-style log files', fromfile_prefix_chars='@')
parser.add_argument('logfile', nargs='*',
help='Log files to process. Use - for stdin.')
parser.add_argument('-l', '--logformat',
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment