def test_gauge(self): output = self._invoke( {'metrics': { 'gauge': dict(name='test_gauge', help='Test Gauge') }}) self.assertEqual(output, 'Tracking metrics: test_gauge') self.assertIn('test_gauge 0.0', self.metrics()) unregister_metrics() output = self._invoke( { 'metrics': { 'gauge': dict(name='test_gauge_with_labels', help='Test Gauge', labels={'target': '{{ request.json.target }}'}) } }, body=dict(target='sample')) self.assertEqual(output, 'Tracking metrics: test_gauge_with_labels') self.assertIn('test_gauge_with_labels{target="sample"} 0.0', self.metrics())
def test_valid_request_with_view_args(self): unregister_metrics() self.server = Server([{ '/testing/<int:a>/<b>/<path:c>': { 'actions': [{ 'log': { 'message': 'Parameters: ' 'a={{ request.view_args["a"] }} ' 'b={{ request.view_args["b"] }} ' 'c={{ request.view_args["c"] }} ' 'x={{ request.view_args["x"] }} <' } }] } }]) self.server.app.testing = True self.client = self.server.app.test_client() with capture_stream() as sout: response = self.client.post('/testing/1/abc/def/ghi', data='{}', content_type='application/json') self.assertEqual(200, response.status_code) content = sout.dumps() self.assertIn('a=1', content) self.assertIn('b=abc', content) self.assertIn('c=def/ghi', content) self.assertIn('x= <', content)
def test_validation_with_templates(self): unregister_metrics() server = Server([{ '/vars': { 'headers': { 'X-Test': '{{ ["templated", "header"]|join("-") }}' }, 'body': { 'key': '{{ ["templated", "body"]|join("-") }}' } } }]) server.app.testing = True client = server.app.test_client() headers = {'X-Test': 'templated-header'} body = {'key': 'templated-body'} response = client.post('/vars', headers=headers, data=json.dumps(body), content_type='application/json') self.assertEqual(200, response.status_code)
def test_histogram(self): output = self._invoke({ 'metrics': { 'histogram': dict(name='test_histogram', help='Test Histogram') } }) self.assertEqual(output, 'Tracking metrics: test_histogram') self.assertIn('test_histogram_count 1.0', self.metrics()) self.assertIn('test_histogram_sum 0.', self.metrics()) self.assertIn('test_histogram_bucket{le=', self.metrics()) unregister_metrics() output = self._invoke({ 'metrics': { 'histogram': dict(name='test_histogram_with_labels', help='Test Histogram', labels={'path': '{{ request.path }}'}) } }) self.assertEqual(output, 'Tracking metrics: test_histogram_with_labels') self.assertIn('test_histogram_with_labels_count{path="/testing"} 1.0', self.metrics()) self.assertIn('test_histogram_with_labels_sum{path="/testing"} 0.', self.metrics()) self.assertIn('test_histogram_with_labels_bucket{le=', self.metrics())
def test_valid_request_with_view_args(self): unregister_metrics() self.server = Server([{ "/testing/<int:a>/<b>/<path:c>": { "actions": [{ "log": { "message": "Parameters: " 'a={{ request.view_args["a"] }} ' 'b={{ request.view_args["b"] }} ' 'c={{ request.view_args["c"] }} ' 'x={{ request.view_args["x"] }} <' } }] } }]) self.server.app.testing = True self.client = self.server.app.test_client() with capture_stream() as sout: response = self.client.post("/testing/1/abc/def/ghi", data="{}", content_type="application/json") self.assertEqual(200, response.status_code) content = sout.dumps() self.assertIn("a=1", content) self.assertIn("b=abc", content) self.assertIn("c=def/ghi", content) self.assertIn("x= <", content)
def test_summary(self): output = self._invoke( {"metrics": {"summary": dict(name="test_summary", help="Test Summary")}} ) self.assertEqual(output, "Tracking metrics: test_summary") self.assertIn("test_summary_count 1.0", self.metrics()) self.assertIn("test_summary_sum 0.", self.metrics()) unregister_metrics() output = self._invoke( { "metrics": { "summary": dict( name="test_summary_with_labels", help="Test Summary", labels={"path": "{{ request.path }}"}, ) } } ) self.assertEqual(output, "Tracking metrics: test_summary_with_labels") self.assertIn( 'test_summary_with_labels_count{path="/testing"} 1.0', self.metrics() ) self.assertIn( 'test_summary_with_labels_sum{path="/testing"} 0.', self.metrics() )
def test_validation_with_templates(self): unregister_metrics() server = Server([{ "/vars": { "headers": { "X-Test": '{{ ["templated", "header"]|join("-") }}' }, "body": { "key": '{{ ["templated", "body"]|join("-") }}' }, } }]) server.app.testing = True client = server.app.test_client() headers = {"X-Test": "templated-header"} body = {"key": "templated-body"} response = client.post( "/vars", headers=headers, data=json.dumps(body), content_type="application/json", ) self.assertEqual(200, response.status_code)
def test_summary(self): output = self._invoke({ 'metrics': { 'summary': dict(name='test_summary', help='Test Summary') } }) self.assertEqual(output, 'Tracking metrics: test_summary') self.assertIn('test_summary_count 1.0', self.metrics()) self.assertIn('test_summary_sum 0.', self.metrics()) unregister_metrics() output = self._invoke({ 'metrics': { 'summary': dict(name='test_summary_with_labels', help='Test Summary', labels={'path': '{{ request.path }}'}) } }) self.assertEqual(output, 'Tracking metrics: test_summary_with_labels') self.assertIn('test_summary_with_labels_count{path="/testing"} 1.0', self.metrics()) self.assertIn('test_summary_with_labels_sum{path="/testing"} 0.', self.metrics())
def test_gauge(self): output = self._invoke( {"metrics": {"gauge": dict(name="test_gauge", help="Test Gauge")}} ) self.assertEqual(output, "Tracking metrics: test_gauge") self.assertIn("test_gauge 0.0", self.metrics()) unregister_metrics() output = self._invoke( { "metrics": { "gauge": dict( name="test_gauge_with_labels", help="Test Gauge", labels={"target": "{{ request.json.target }}"}, ) } }, body=dict(target="sample"), ) self.assertEqual(output, "Tracking metrics: test_gauge_with_labels") self.assertIn('test_gauge_with_labels{target="sample"} 0.0', self.metrics())
def test_multiple_endpoints(self): unregister_metrics() server = Server( [ { "/one": { "actions": [{"metrics": {"counter": {"name": "metric_one"}}}] }, "/two": { "actions": [ {"metrics": {"counter": {"name": "metric_two"}}}, {"metrics": {"counter": {"name": "metric_xyz"}}}, ] }, } ] ) server.app.testing = True client = server.app.test_client() self._server = server client.post( "/one", headers={"Content-Type": "application/json"}, data='{"test":"1"}', content_type="application/json", ) self.assertIn("metric_one_total 1.0", self.metrics()) self.assertIn("metric_two_total 0.0", self.metrics()) self.assertIn("metric_xyz_total 0.0", self.metrics()) client.post( "/one", headers={"Content-Type": "application/json"}, data='{"test":"2"}', content_type="application/json", ) self.assertIn("metric_one_total 2.0", self.metrics()) self.assertIn("metric_two_total 0.0", self.metrics()) self.assertIn("metric_xyz_total 0.0", self.metrics()) client.post( "/two", headers={"Content-Type": "application/json"}, data='{"test":"3"}', content_type="application/json", ) self.assertIn("metric_one_total 2.0", self.metrics()) self.assertIn("metric_two_total 1.0", self.metrics()) self.assertIn("metric_xyz_total 1.0", self.metrics())
def test_empty_endpoint_settings_accept_empty_body(self): unregister_metrics() server = Server([{'/empty': None}]) server.app.testing = True client = server.app.test_client() response = client.post('/empty') self.assertEqual(200, response.status_code)
def test_missing_endpoint_route_throws_exception(self): unregister_metrics() self.assertRaises(ConfigurationException, Server, [{ None: { 'method': 'GET' } }]) unregister_metrics() self.assertRaises(ConfigurationException, Server, [{ '': { 'method': 'GET' } }])
def test_async_request(self): unregister_metrics() self.server = Server([{ "/testing": { "body": { "key": "value" }, "async": True, "actions": [ { "sleep": { "seconds": 0.2 } }, { "log": { "message": "Serving {{ request.path }} with key={{ request.json.key }}" } }, ], } }]) self.server.app.testing = True self.client = self.server.app.test_client() _stdout = sys.stdout _output = [] class CapturingStdout(object): def write(self, content): _output.append(content) sys.stdout = CapturingStdout() try: self._check(200, headers=None, body={"key": "value"}) self.assertNotIn("Serving /testing with key=value", "".join(_output)) time.sleep(0.5) self.assertIn("Serving /testing with key=value", "".join(_output)) finally: sys.stdout = _stdout
def test_async_request(self): unregister_metrics() self.server = Server([{ '/testing': { 'body': { 'key': 'value' }, 'async': True, 'actions': [{ 'sleep': { 'seconds': 0.2 } }, { 'log': { 'message': 'Serving {{ request.path }} with key={{ request.json.key }}' } }] } }]) self.server.app.testing = True self.client = self.server.app.test_client() _stdout = sys.stdout _output = [] class CapturingStdout(object): def write(self, content): _output.append(content) sys.stdout = CapturingStdout() try: self._check(200, headers=None, body={'key': 'value'}) self.assertNotIn('Serving /testing with key=value', ''.join(_output)) time.sleep(0.5) self.assertIn('Serving /testing with key=value', ''.join(_output)) finally: sys.stdout = _stdout
def setUp(self): unregister_metrics() self.server = Server([{ '/testing': { 'headers': { 'X-Sample': '^ab[0-9]+$' }, 'body': { 'key': 'value', 'item': { 'prop': '^[0-9]*$' } } } }]) self.server.app.testing = True self.client = self.server.app.test_client()
def setUp(self): unregister_metrics() self.server = Server([{ "/testing": { "headers": { "X-Sample": "^ab[0-9]+$" }, "body": { "key": "value", "item": { "prop": "^[0-9]*$" } }, } }]) self.server.app.testing = True self.client = self.server.app.test_client()
def test_get_request(self): unregister_metrics() server = Server([{ '/get': { 'method': 'GET', 'headers': { 'X-Method': '(GET|HEAD)' } } }]) server.app.testing = True client = server.app.test_client() response = client.get('/get', headers={'X-Method': 'GET'}) self.assertEqual(200, response.status_code) response = client.get('/get', headers={'X-Method': 'Invalid'}) self.assertEqual(409, response.status_code)
def test_get_request(self): unregister_metrics() server = Server([{ "/get": { "method": "GET", "headers": { "X-Method": "(GET|HEAD)" } } }]) server.app.testing = True client = server.app.test_client() response = client.get("/get", headers={"X-Method": "GET"}) self.assertEqual(200, response.status_code) response = client.get("/get", headers={"X-Method": "Invalid"}) self.assertEqual(409, response.status_code)
def test_histogram(self): output = self._invoke( { "metrics": { "histogram": dict(name="test_histogram", help="Test Histogram") } } ) self.assertEqual(output, "Tracking metrics: test_histogram") self.assertIn("test_histogram_count 1.0", self.metrics()) self.assertIn("test_histogram_sum 0.", self.metrics()) self.assertIn("test_histogram_bucket{le=", self.metrics()) unregister_metrics() output = self._invoke( { "metrics": { "histogram": dict( name="test_histogram_with_labels", help="Test Histogram", labels={"path": "{{ request.path }}"}, ) } } ) self.assertEqual(output, "Tracking metrics: test_histogram_with_labels") self.assertIn( 'test_histogram_with_labels_count{path="/testing"} 1.0', self.metrics() ) self.assertIn( 'test_histogram_with_labels_sum{path="/testing"} 0.', self.metrics() ) self.assertIn("test_histogram_with_labels_bucket{le=", self.metrics())
def test_counter(self): output = self._invoke( {"metrics": {"counter": dict(name="test_counter", help="Test Counter")}} ) self.assertEqual(output, "Tracking metrics: test_counter") self.assertIn("test_counter_total 1.0", self.metrics()) unregister_metrics() output = self._invoke( { "metrics": { "counter": dict( name="test_counter_with_labels", help="Test Counter", labels={"code": "{{ response.status_code }}"}, ) } } ) self.assertEqual(output, "Tracking metrics: test_counter_with_labels") self.assertIn('test_counter_with_labels_total{code="200"} 1.0', self.metrics())
def test_counter(self): output = self._invoke({ 'metrics': { 'counter': dict(name='test_counter', help='Test Counter') } }) self.assertEqual(output, 'Tracking metrics: test_counter') self.assertIn('test_counter 1.0', self.metrics()) unregister_metrics() output = self._invoke({ 'metrics': { 'counter': dict(name='test_counter_with_labels', help='Test Counter', labels={'code': '{{ response.status_code }}'}) } }) self.assertEqual(output, 'Tracking metrics: test_counter_with_labels') self.assertIn('test_counter_with_labels{code="200"} 1.0', self.metrics())
def test_metrics(self): unregister_metrics() self.server = Server([{ '/test/post': { 'async': True, 'actions': [{ 'sleep': { 'seconds': 0.01 } }, { 'log': {} }] }, '/test/put': { 'method': 'PUT', 'actions': [{ 'log': {} }, { 'execute': { 'command': 'echo "Executing command"' } }] } }]) self.server.app.testing = True self.client = self.server.app.test_client() for _ in range(2): response = self.client.post('/test/post', data=json.dumps({'unused': 1}), content_type='application/json') self.assertEqual(response.status_code, 200) for _ in range(3): response = self.client.put('/test/put', data=json.dumps({'unused': 1}), content_type='application/json') self.assertEqual(response.status_code, 200) time.sleep(0.1) response = self.client.get('/metrics') self.assertEqual(response.status_code, 200) metrics = response.data.decode('utf-8') self.assertIn('python_info{', metrics) self.assertIn('process_start_time_seconds ', metrics) self.assertIn( 'flask_http_request_total{' 'method="POST",status="200"} 2.0', metrics) self.assertIn( 'flask_http_request_total{' 'method="PUT",status="200"} 3.0', metrics) self.assertIn( 'flask_http_request_duration_seconds_bucket{' 'le="5.0",method="POST",path="/test/post",status="200"} 2.0', metrics) self.assertIn( 'flask_http_request_duration_seconds_count{' 'method="POST",path="/test/post",status="200"} 2.0', metrics) self.assertIn( 'flask_http_request_duration_seconds_sum{' 'method="POST",path="/test/post",status="200"}', metrics) self.assertIn( 'flask_http_request_duration_seconds_bucket{' 'le="0.5",method="PUT",path="/test/put",status="200"} 3.0', metrics) self.assertIn( 'flask_http_request_duration_seconds_count{' 'method="PUT",path="/test/put",status="200"} 3.0', metrics) self.assertIn( 'flask_http_request_duration_seconds_sum{' 'method="PUT",path="/test/put",status="200"}', metrics) self.assertIn( 'webhook_proxy_actions_count{' 'action_index="0",action_type="sleep",' 'http_method="POST",http_route="/test/post"} 2.0', metrics) self.assertIn( 'webhook_proxy_actions_sum{' 'action_index="0",action_type="sleep",' 'http_method="POST",http_route="/test/post"}', metrics) self.assertIn( 'webhook_proxy_actions_count{' 'action_index="1",action_type="log",' 'http_method="POST",http_route="/test/post"} 2.0', metrics) self.assertIn( 'webhook_proxy_actions_sum{' 'action_index="1",action_type="log",' 'http_method="POST",http_route="/test/post"}', metrics) self.assertIn( 'webhook_proxy_actions_count{' 'action_index="0",action_type="log",' 'http_method="PUT",http_route="/test/put"} 3.0', metrics) self.assertIn( 'webhook_proxy_actions_sum{' 'action_index="0",action_type="log",' 'http_method="PUT",http_route="/test/put"}', metrics) self.assertIn( 'webhook_proxy_actions_count{' 'action_index="1",action_type="execute",' 'http_method="PUT",http_route="/test/put"} 3.0', metrics) self.assertIn( 'webhook_proxy_actions_sum{' 'action_index="1",action_type="execute",' 'http_method="PUT",http_route="/test/put"}', metrics)
def test_metrics(self): unregister_metrics() self.server = Server([{ "/test/post": { "async": True, "actions": [{ "sleep": { "seconds": 0.01 } }, { "log": {} }], }, "/test/put": { "method": "PUT", "actions": [ { "log": {} }, { "execute": { "command": 'echo "Executing command"' } }, ], }, }]) self.server.app.testing = True self.client = self.server.app.test_client() for _ in range(2): response = self.client.post( "/test/post", data=json.dumps({"unused": 1}), content_type="application/json", ) self.assertEqual(response.status_code, 200) for _ in range(3): response = self.client.put( "/test/put", data=json.dumps({"unused": 1}), content_type="application/json", ) self.assertEqual(response.status_code, 200) time.sleep(0.1) response = self.client.get("/metrics") self.assertEqual(response.status_code, 200) metrics = response.data.decode("utf-8") self.assertIn("python_info{", metrics) self.assertIn("process_start_time_seconds ", metrics) self.assertIn( "flask_http_request_total{" 'method="POST",status="200"} 2.0', metrics) self.assertIn( "flask_http_request_total{" 'method="PUT",status="200"} 3.0', metrics) self.assertIn( "flask_http_request_duration_seconds_bucket{" 'le="5.0",method="POST",path="/test/post",status="200"} 2.0', metrics, ) self.assertIn( "flask_http_request_duration_seconds_count{" 'method="POST",path="/test/post",status="200"} 2.0', metrics, ) self.assertIn( "flask_http_request_duration_seconds_sum{" 'method="POST",path="/test/post",status="200"}', metrics, ) self.assertIn( "flask_http_request_duration_seconds_bucket{" 'le="0.5",method="PUT",path="/test/put",status="200"} 3.0', metrics, ) self.assertIn( "flask_http_request_duration_seconds_count{" 'method="PUT",path="/test/put",status="200"} 3.0', metrics, ) self.assertIn( "flask_http_request_duration_seconds_sum{" 'method="PUT",path="/test/put",status="200"}', metrics, ) self.assertIn( "webhook_proxy_actions_count{" 'action_index="0",action_type="sleep",' 'http_method="POST",http_route="/test/post"} 2.0', metrics, ) self.assertIn( "webhook_proxy_actions_sum{" 'action_index="0",action_type="sleep",' 'http_method="POST",http_route="/test/post"}', metrics, ) self.assertIn( "webhook_proxy_actions_count{" 'action_index="1",action_type="log",' 'http_method="POST",http_route="/test/post"} 2.0', metrics, ) self.assertIn( "webhook_proxy_actions_sum{" 'action_index="1",action_type="log",' 'http_method="POST",http_route="/test/post"}', metrics, ) self.assertIn( "webhook_proxy_actions_count{" 'action_index="0",action_type="log",' 'http_method="PUT",http_route="/test/put"} 3.0', metrics, ) self.assertIn( "webhook_proxy_actions_sum{" 'action_index="0",action_type="log",' 'http_method="PUT",http_route="/test/put"}', metrics, ) self.assertIn( "webhook_proxy_actions_count{" 'action_index="1",action_type="execute",' 'http_method="PUT",http_route="/test/put"} 3.0', metrics, ) self.assertIn( "webhook_proxy_actions_sum{" 'action_index="1",action_type="execute",' 'http_method="PUT",http_route="/test/put"}', metrics, )
def tearDown(self): unregister_metrics()
def test_multiple_endpoints(self): unregister_metrics() server = Server([{ '/one': { 'actions': [{ 'metrics': { 'counter': { 'name': 'metric_one' } } }] }, '/two': { 'actions': [{ 'metrics': { 'counter': { 'name': 'metric_two' } } }, { 'metrics': { 'counter': { 'name': 'metric_xyz' } } }] } }]) server.app.testing = True client = server.app.test_client() self._server = server client.post('/one', headers={'Content-Type': 'application/json'}, data='{"test":"1"}', content_type='application/json') self.assertIn('metric_one 1.0', self.metrics()) self.assertIn('metric_two 0.0', self.metrics()) self.assertIn('metric_xyz 0.0', self.metrics()) client.post('/one', headers={'Content-Type': 'application/json'}, data='{"test":"2"}', content_type='application/json') self.assertIn('metric_one 2.0', self.metrics()) self.assertIn('metric_two 0.0', self.metrics()) self.assertIn('metric_xyz 0.0', self.metrics()) client.post('/two', headers={'Content-Type': 'application/json'}, data='{"test":"3"}', content_type='application/json') self.assertIn('metric_one 2.0', self.metrics()) self.assertIn('metric_two 1.0', self.metrics()) self.assertIn('metric_xyz 1.0', self.metrics())