forked from chromano/apache-log-replay
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for proxy server and for speeding up the replay. Refact…
…ored and cleaned up the code and added option parsing. Added a readme file.
- Loading branch information
Adrian Lienhard
committed
May 31, 2011
1 parent
e05476b
commit 3e6606d
Showing
2 changed files
with
92 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Script to replay HTTP requests from an Apache access logfile | ||
|
||
Features | ||
|
||
- Takes the time between requests into account | ||
- Replaying can be sped up by a given factor | ||
- Optionally send all requests to a selected (proxy) server | ||
|
||
## Installation | ||
|
||
Requires Python >= 2.6 | ||
|
||
Simply download the file and execute it... | ||
|
||
## Usage | ||
|
||
Usage: apache-log-replay.py [options] logfile | ||
|
||
Options: | ||
-h, --help show this help message and exit | ||
-p PROXY, --proxy=PROXY | ||
send requests to server PROXY | ||
-s SPEEDUP, --speedup=SPEEDUP | ||
make time run faster by factor SPEEDUP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,88 @@ | ||
#!/usr/bin/env python2.5 | ||
from datetime import datetime | ||
"""Replay requests from an HTTP access log file. | ||
- Takes time between requests into account, with option to speed up the replay. | ||
- Allows one to send all requests to a selected server (proxy). | ||
""" | ||
|
||
import sys | ||
import time | ||
from urllib2 import urlopen | ||
import urllib2 | ||
from datetime import datetime | ||
from optparse import OptionParser | ||
|
||
def main(host, filename): | ||
logfile = open(filename, "r") | ||
requests = [] | ||
for line in logfile: | ||
parts = line.split(" ") | ||
if len(parts) != 24: | ||
continue | ||
time_text = parts[3][1:] | ||
request_time = datetime.strptime(time_text, "%d/%b/%Y:%H:%M:%S") | ||
path = parts[6] | ||
requests.append((request_time, path)) | ||
if not requests: | ||
print "Seems like I don't know how to parse this file!" | ||
return | ||
# Constants that specify access log format (indices | ||
# specify position after splitting on spaces) | ||
HOST_INDEX = 0 | ||
TIME_INDEX = 3 | ||
PATH_INDEX = 6 | ||
|
||
def main(filename, proxy, speedup=1): | ||
"""Setup and start replaying.""" | ||
requests = _parse_logfile(filename) | ||
_setup_http_client(proxy) | ||
_replay(requests, speedup) | ||
|
||
def _replay(requests, speedup): | ||
"""Replay the requests passed as argument""" | ||
total_delta = requests[-1][0] - requests[0][0] | ||
print "%d requests to go (time: %s)" % (len(requests), total_delta) | ||
last_time = requests[0][0] | ||
for request_time, path in requests: | ||
time_delta = request_time - last_time | ||
for request_time, host, path in requests: | ||
time_delta = (request_time - last_time) // speedup | ||
if time_delta: | ||
if time_delta.seconds > 10: | ||
if time_delta and time_delta.seconds > 10: | ||
print "(next request in %d seconds)" % time_delta.seconds | ||
time.sleep(time_delta.seconds) | ||
last_time = request_time | ||
url = host + path | ||
url = "http://" + host + path | ||
try: | ||
req_result = "OK" | ||
urlopen(url) | ||
urllib2.urlopen(url) | ||
except Exception: | ||
req_result = "FAILED" | ||
print ("[%s] REQUEST: %s -- %s" | ||
% (request_time.strftime("%H:%M:%S"), url, req_result)) | ||
% (request_time.strftime("%H:%M:%S"), url, req_result)) | ||
|
||
def usage(): | ||
print "%s <host> <logfile>" % sys.argv[0] | ||
def _setup_http_client(proxy): | ||
"""Configure proxy server and install HTTP opener""" | ||
proxy_config = {'http': proxy} if proxy else {} | ||
proxy_handler = urllib2.ProxyHandler(proxy_config) | ||
opener = urllib2.build_opener(proxy_handler) | ||
urllib2.install_opener(opener) | ||
|
||
def _parse_logfile(filename): | ||
"""Parse the logfile and return a list with tuples of the form | ||
(<request time>, <requested host>, <requested url>) | ||
""" | ||
logfile = open(filename, "r") | ||
requests = [] | ||
for line in logfile: | ||
parts = line.split(" ") | ||
time_text = parts[TIME_INDEX][1:] | ||
request_time = datetime.strptime(time_text, "%d/%b/%Y:%H:%M:%S") | ||
host = parts[HOST_INDEX] | ||
path = parts[PATH_INDEX] | ||
requests.append((request_time, host, path)) | ||
if not requests: | ||
print "Seems like I don't know how to parse this file!" | ||
return requests | ||
|
||
if __name__ == "__main__": | ||
if not len(sys.argv) == 3: | ||
usage() | ||
"""Parse command line options.""" | ||
usage = "usage: %prog [options] logfile" | ||
parser = OptionParser(usage) | ||
parser.add_option('-p', '--proxy', | ||
help='send requests to server PROXY', | ||
dest='proxy', | ||
default=None) | ||
parser.add_option('-s', '--speedup', | ||
help='make time run faster by factor SPEEDUP', | ||
dest='speedup', | ||
type='int', | ||
default=1) | ||
(options, args) = parser.parse_args() | ||
if len(args) == 1: | ||
main(args[0], options.proxy, options.speedup) | ||
else: | ||
main(sys.argv[1], sys.argv[2]) | ||
|
||
parser.error("incorrect number of arguments") | ||