From b955a6579b28fe359ddaee0aaf65b9fc6549fd09 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Tue, 15 Dec 2015 14:03:11 +0000 Subject: [PATCH 1/3] Using the extended log file format for HTTP --- ripe/atlas/tools/renderers/http.py | 44 +++++++++++++++++++++++++++++- tests/__init__.py | 2 ++ tests/renderers/__init__.py | 2 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/ripe/atlas/tools/renderers/http.py b/ripe/atlas/tools/renderers/http.py index 92bea39..427dbc1 100644 --- a/ripe/atlas/tools/renderers/http.py +++ b/ripe/atlas/tools/renderers/http.py @@ -13,12 +13,54 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +from ..helpers.colours import colourise + from .base import Renderer as BaseRenderer +from .base import Result class Renderer(BaseRenderer): + """ + We're abusing the Extended Log File Format here to render the result, + amending it to include a few things not originally specified in the W3C + Working Draft: http://www.w3.org/TR/WD-logfile.html Namely: + http-version, header-bytes, and body-bytes + """ RENDERS = [BaseRenderer.TYPE_HTTP] + COLOURS = { + "2": "green", + "3": "blue", + "4": "yellow", + "5": "red" + } def on_result(self, result, probes=None): - print("Not ready yet\n") + r = "#Version: 1.0\n#Date: {}\n#Fields: {}\n".format( + result.created.strftime("%Y-%m-%d %H:%M:%S"), + "cs-method cs-uri c-ip s-ip sc-status time-taken http-version " + "header-bytes body-bytes" + ) + for response in result.responses: + r += self._colourise_by_status( + "{} {} {} {} {} {} {} {} {}\n".format( + result.method, + result.uri, + response.source_address, + response.destination_address, + response.code, + response.response_time, + response.version, + response.head_size, + response.body_size + ), + response.code + ) + + return Result(r + "\n", result.probe_id) + + def _colourise_by_status(self, output, status): + try: + return colourise(output, self.COLOURS[str(status)[0]]) + except (IndexError, KeyError): + return colourise(output, "red") diff --git a/tests/__init__.py b/tests/__init__.py index 7f98f57..76bab3e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -23,6 +23,7 @@ from .helpers import TestArgumentTypeHelper from .renderers import ( TestPingRenderer, + TestHttpRenderer, TestSSLConsistency, TestAggregatePing, TestRawRenderer, @@ -37,6 +38,7 @@ TestReportCommand, TestArgumentTypeHelper, TestPingRenderer, + TestHttpRenderer, TestSSLConsistency, TestAggregatePing, TestRawRenderer, diff --git a/tests/renderers/__init__.py b/tests/renderers/__init__.py index 27d49f8..0e63ac1 100644 --- a/tests/renderers/__init__.py +++ b/tests/renderers/__init__.py @@ -14,12 +14,14 @@ # along with this program. If not, see . from .ping import TestPingRenderer +from .http import TestHttpRenderer from .aggregate_ping import TestAggregatePing from .ssl_consistency import TestSSLConsistency from .raw import TestRawRenderer __all__ = [ TestPingRenderer, + TestHttpRenderer, TestAggregatePing, TestSSLConsistency ] From 58b1293d2ba7798ceee2280439ad6d54937c51cc Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Tue, 15 Dec 2015 14:15:50 +0000 Subject: [PATCH 2/3] Fixing the NTP placeholder so it at least doesn't explode --- ripe/atlas/tools/renderers/ntp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ripe/atlas/tools/renderers/ntp.py b/ripe/atlas/tools/renderers/ntp.py index 7d9a891..54ba339 100644 --- a/ripe/atlas/tools/renderers/ntp.py +++ b/ripe/atlas/tools/renderers/ntp.py @@ -14,6 +14,7 @@ # along with this program. If not, see . from .base import Renderer as BaseRenderer +from .base import Result class Renderer(BaseRenderer): @@ -21,4 +22,4 @@ class Renderer(BaseRenderer): RENDERS = [BaseRenderer.TYPE_NTP] def on_result(self, result, probes=None): - print("Not ready yet\n") + return Result("Not ready yet\n", result.probe_id) From 0710ee45f812321b101822ae9ecfb06aee07939c Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Tue, 15 Dec 2015 14:28:59 +0000 Subject: [PATCH 3/3] Oops, forgot to include the tests I was importing --- tests/renderers/http.py | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/renderers/http.py diff --git a/tests/renderers/http.py b/tests/renderers/http.py new file mode 100644 index 0000000..31a2048 --- /dev/null +++ b/tests/renderers/http.py @@ -0,0 +1,48 @@ +# Copyright (c) 2015 RIPE NCC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import unittest + +from ripe.atlas.sagan import Result +from ripe.atlas.tools.renderers.http import Renderer + + +class TestHttpRenderer(unittest.TestCase): + + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + self.basic = Result.get('{"lts":64,"from":"217.13.64.36","msm_id":2841267,"fw":4720,"timestamp":1450185727,"uri":"http://at-vie-as1120.anchors.atlas.ripe.net:80/4096","prb_id":1,"result":[{"rt":45.953289,"src_addr":"217.13.64.36","hsize":131,"af":4,"bsize":1668618,"res":200,"method":"GET","ver":"1.1","dst_addr":"193.171.255.2"}],"group_id":2841267,"type":"http","msm_name":"HTTPGet"}') + self.multiple = Result.get('{"lts":64,"from":"217.13.64.36","msm_id":2841267,"fw":4720,"timestamp":1450185727,"uri":"http://at-vie-as1120.anchors.atlas.ripe.net:80/4096","prb_id":1,"result":[{"rt":45.953289,"src_addr":"217.13.64.36","hsize":131,"af":4,"bsize":1668618,"res":200,"method":"GET","ver":"1.1","dst_addr":"193.171.255.2"},{"rt":45.953289,"src_addr":"217.13.64.36","hsize":131,"af":4,"bsize":1668618,"res":200,"method":"GET","ver":"1.1","dst_addr":"193.171.255.2"}],"group_id":2841267,"type":"http","msm_name":"HTTPGet"}') + + def test_basic(self): + expected = ( + '#Version: 1.0\n' + '#Date: 2015-12-15 13:22:07\n' + '#Fields: cs-method cs-uri c-ip s-ip sc-status time-taken http-version header-bytes body-bytes\n' + 'GET http://at-vie-as1120.anchors.atlas.ripe.net:80/4096 217.13.64.36 193.171.255.2 200 45.953289 1.1 131 1668618\n\n' + ) + self.assertEqual(Renderer().on_result(self.basic), expected) + self.assertEqual(Renderer().on_result(self.basic).probe_id, 1) + + def test_multiple(self): + expected = ( + '#Version: 1.0\n' + '#Date: 2015-12-15 13:22:07\n' + '#Fields: cs-method cs-uri c-ip s-ip sc-status time-taken http-version header-bytes body-bytes\n' + 'GET http://at-vie-as1120.anchors.atlas.ripe.net:80/4096 217.13.64.36 193.171.255.2 200 45.953289 1.1 131 1668618\n' + 'GET http://at-vie-as1120.anchors.atlas.ripe.net:80/4096 217.13.64.36 193.171.255.2 200 45.953289 1.1 131 1668618\n\n' + ) + self.assertEqual(Renderer().on_result(self.multiple), expected) + self.assertEqual(Renderer().on_result(self.basic).probe_id, 1)