cloudflare/cloudflared
Publicmirrored from https://github.com/cloudflare/cloudflaredAvailable
component-tests/test_logging.py
93lines · modecode
| 1 | #!/usr/bin/env python |
| 2 | import json |
| 3 | import os |
| 4 | from util import start_cloudflared, wait_tunnel_ready, send_requests, LOGGER |
| 5 | |
| 6 | |
| 7 | class TestLogging: |
| 8 | # TODO: Test logging when running as a service https://jira.cfops.it/browse/TUN-4082 |
| 9 | # Rolling logger rotate log files after 1 MB |
| 10 | rotate_after_size = 1000 * 1000 |
| 11 | default_log_file = "cloudflared.log" |
| 12 | expect_message = "Starting tunnel" |
| 13 | |
| 14 | def test_logging_to_terminal(self, tmp_path, component_tests_config): |
| 15 | config = component_tests_config() |
| 16 | with start_cloudflared(tmp_path, config, new_process=True) as cloudflared: |
| 17 | wait_tunnel_ready(tunnel_url=config.get_url()) |
| 18 | self.assert_log_to_terminal(cloudflared) |
| 19 | |
| 20 | def test_logging_to_file(self, tmp_path, component_tests_config): |
| 21 | log_file = tmp_path / self.default_log_file |
| 22 | extra_config = { |
| 23 | # Convert from pathlib.Path to str |
| 24 | "logfile": str(log_file), |
| 25 | } |
| 26 | config = component_tests_config(extra_config) |
| 27 | with start_cloudflared(tmp_path, config, new_process=True, capture_output=False): |
| 28 | wait_tunnel_ready(tunnel_url=config.get_url()) |
| 29 | self.assert_log_in_file(log_file) |
| 30 | self.assert_json_log(log_file) |
| 31 | |
| 32 | def test_logging_to_dir(self, tmp_path, component_tests_config): |
| 33 | log_dir = tmp_path / "logs" |
| 34 | extra_config = { |
| 35 | "loglevel": "debug", |
| 36 | # Convert from pathlib.Path to str |
| 37 | "log-directory": str(log_dir), |
| 38 | } |
| 39 | config = component_tests_config(extra_config) |
| 40 | with start_cloudflared(tmp_path, config, new_process=True, capture_output=False): |
| 41 | wait_tunnel_ready(tunnel_url=config.get_url()) |
| 42 | self.assert_log_to_dir(config, log_dir) |
| 43 | |
| 44 | def assert_log_to_terminal(self, cloudflared): |
| 45 | stderr = cloudflared.stderr.read(200) |
| 46 | # cloudflared logs the following when it first starts |
| 47 | # 2021-03-10T12:30:39Z INF Starting tunnel tunnelID=<tunnel ID> |
| 48 | assert self.expect_message.encode( |
| 49 | ) in stderr, f"{stderr} doesn't contain {self.expect_message}" |
| 50 | |
| 51 | def assert_log_in_file(self, file, expect_message=""): |
| 52 | with open(file, "r") as f: |
| 53 | log = f.read(200) |
| 54 | # cloudflared logs the following when it first starts |
| 55 | # {"level":"info","tunnelID":"<tunnel ID>","time":"2021-03-10T12:21:13Z","message":"Starting tunnel"} |
| 56 | assert self.expect_message in log, f"{log} doesn't contain {self.expect_message}" |
| 57 | |
| 58 | def assert_json_log(self, file): |
| 59 | with open(file, "r") as f: |
| 60 | line = f.readline() |
| 61 | json_log = json.loads(line) |
| 62 | self.assert_in_json(json_log, "level") |
| 63 | self.assert_in_json(json_log, "time") |
| 64 | self.assert_in_json(json_log, "message") |
| 65 | |
| 66 | def assert_in_json(self, j, key): |
| 67 | assert key in j, f"{key} is not in j" |
| 68 | |
| 69 | def assert_log_to_dir(self, config, log_dir): |
| 70 | max_batches = 3 |
| 71 | batch_requests = 1000 |
| 72 | for _ in range(max_batches): |
| 73 | send_requests(config.get_url(), |
| 74 | batch_requests, require_ok=False) |
| 75 | files = os.listdir(log_dir) |
| 76 | if len(files) == 2: |
| 77 | current_log_file_index = files.index(self.default_log_file) |
| 78 | current_file = log_dir / files[current_log_file_index] |
| 79 | stats = os.stat(current_file) |
| 80 | assert stats.st_size > 0 |
| 81 | self.assert_json_log(current_file) |
| 82 | |
| 83 | # One file is the current log file, the other is the rotated log file |
| 84 | rotated_log_file_index = 0 if current_log_file_index == 1 else 1 |
| 85 | rotated_file = log_dir / files[rotated_log_file_index] |
| 86 | stats = os.stat(rotated_file) |
| 87 | assert stats.st_size > self.rotate_after_size |
| 88 | self.assert_log_in_file(rotated_file) |
| 89 | self.assert_json_log(current_file) |
| 90 | return |
| 91 | |
| 92 | raise Exception( |
| 93 | f"Log file isn't rotated after sending {max_batches * batch_requests} requests") |
| 94 | |