Merge lp:~sseman/juju-chaos-monkey/logging into lp:juju-chaos-monkey

Proposed by Seman
Status: Merged
Merged at revision: 3
Proposed branch: lp:~sseman/juju-chaos-monkey/logging
Merge into: lp:juju-chaos-monkey
Diff against target: 289 lines (+115/-23)
5 files modified
chaos/kill.py (+6/-5)
chaos/net.py (+14/-13)
runner.py (+11/-1)
tests/test_utility.py (+67/-1)
utility.py (+17/-3)
To merge this branch: bzr merge lp:~sseman/juju-chaos-monkey/logging
Reviewer Review Type Date Requested Status
John George (community) Approve
Review via email: mp+257917@code.launchpad.net

Description of the change

Added logging and timestamp.

To post a comment you must log in.
lp:~sseman/juju-chaos-monkey/logging updated
4. By Seman

Updated error logging function.

Revision history for this message
John George (jog) wrote :

You would not need to provide and maintain the helper log() and log_error() functions if only the root logger was used. Then to write to the log each file would just need to import the logger module and call logger.info(), logger.warning, logger.error(), logger,critical(), logger.debug or logger.exception().

review: Needs Fixing
Revision history for this message
John George (jog) :
lp:~sseman/juju-chaos-monkey/logging updated
5. By Seman

Removed log() and log_error()

Revision history for this message
Seman (sseman) wrote :

Thank you John for the review. I removed log() and log_error(). Also, see inline comments.

Revision history for this message
John George (jog) wrote :

Thank you.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'chaos/kill.py'
--- chaos/kill.py 2015-04-29 19:57:39 +0000
+++ chaos/kill.py 2015-04-30 22:20:24 +0000
@@ -1,9 +1,10 @@
1import logging
2
1from chaos_monkey_base import (3from chaos_monkey_base import (
2 Chaos,4 Chaos,
3 ChaosMonkeyBase,5 ChaosMonkeyBase,
4)6)
5from utility import (7from utility import (
6 log,
7 NotFound,8 NotFound,
8 run_shell_command,9 run_shell_command,
9)10)
@@ -29,20 +30,20 @@
29 return pids.split(' ')30 return pids.split(' ')
3031
31 def kill_jujud(self, quiet_mode=True):32 def kill_jujud(self, quiet_mode=True):
32 log("Kill.kill_jujud")33 logging.info("Kill.kill_jujud")
33 pids = self.get_pids('jujud')34 pids = self.get_pids('jujud')
34 if not pids:35 if not pids:
35 log("Jujud process ID not found")36 logging.error("Jujud process ID not found")
36 if not quiet_mode:37 if not quiet_mode:
37 raise NotFound('Process id not found')38 raise NotFound('Process id not found')
38 return39 return
39 run_shell_command('kill -s SIGKILL ' + pids[0])40 run_shell_command('kill -s SIGKILL ' + pids[0])
4041
41 def kill_mongodb(self, quiet_mode=True):42 def kill_mongodb(self, quiet_mode=True):
42 log("Kill.kill_mongod")43 logging.info("Kill.kill_mongod")
43 pids = self.get_pids('mongod')44 pids = self.get_pids('mongod')
44 if not pids:45 if not pids:
45 log("MongoDB process ID not found")46 logging.error("MongoDB process ID not found")
46 if not quiet_mode:47 if not quiet_mode:
47 raise NotFound('Process id not found')48 raise NotFound('Process id not found')
48 return49 return
4950
=== modified file 'chaos/net.py'
--- chaos/net.py 2015-04-29 19:57:39 +0000
+++ chaos/net.py 2015-04-30 22:20:24 +0000
@@ -1,9 +1,10 @@
1import logging
2
1from chaos_monkey_base import (3from chaos_monkey_base import (
2 Chaos,4 Chaos,
3 ChaosMonkeyBase,5 ChaosMonkeyBase,
4)6)
5from utility import (7from utility import (
6 log,
7 run_shell_command,8 run_shell_command,
8)9)
910
@@ -22,62 +23,62 @@
22 return cls()23 return cls()
2324
24 def reset(self):25 def reset(self):
25 log("Net.reset ")26 logging.info("Net.reset ")
26 cmd = 'ufw reset'27 cmd = 'ufw reset'
27 run_shell_command(cmd)28 run_shell_command(cmd)
2829
29 def default_deny(self):30 def default_deny(self):
30 log("Net.default_deny")31 logging.info("Net.default_deny")
31 cmd = "ufw default deny"32 cmd = "ufw default deny"
32 run_shell_command(cmd)33 run_shell_command(cmd)
3334
34 def default_allow(self):35 def default_allow(self):
35 log("Net.default_allow")36 logging.info("Net.default_allow")
36 cmd = "ufw default allow"37 cmd = "ufw default allow"
37 run_shell_command(cmd)38 run_shell_command(cmd)
3839
39 def allow_ssh(self):40 def allow_ssh(self):
40 log("Net.allow_ssh")41 logging.info("Net.allow_ssh")
41 cmd = 'ufw allow ssh'42 cmd = 'ufw allow ssh'
42 run_shell_command(cmd)43 run_shell_command(cmd)
4344
44 def deny_ssh(self):45 def deny_ssh(self):
45 log("Net.deny_ssh")46 logging.info("Net.deny_ssh")
46 cmd = 'ufw deny ssh'47 cmd = 'ufw deny ssh'
47 run_shell_command(cmd)48 run_shell_command(cmd)
4849
49 def deny_all_incoming_and_outgoing_except_ssh(self):50 def deny_all_incoming_and_outgoing_except_ssh(self):
50 log("Net.deny_all_incoming_and_outgoing_except_ssh")51 logging.info("Net.deny_all_incoming_and_outgoing_except_ssh")
51 self.deny_all_incoming_except_ssh()52 self.deny_all_incoming_except_ssh()
52 self.deny_all_outgoing_except_ssh()53 self.deny_all_outgoing_except_ssh()
5354
54 def allow_all_incoming_and_outgoing(self):55 def allow_all_incoming_and_outgoing(self):
55 log("Net.allow_all_incoming_and_outgoing")56 logging.info("Net.allow_all_incoming_and_outgoing")
56 self.allow_all_incoming()57 self.allow_all_incoming()
57 self.allow_all_outgoing()58 self.allow_all_outgoing()
5859
59 def deny_all_incoming_except_ssh(self):60 def deny_all_incoming_except_ssh(self):
60 log("Net.deny_all_incoming_except_ssh")61 logging.info("Net.deny_all_incoming_except_ssh")
61 self.allow_ssh()62 self.allow_ssh()
62 self.default_deny()63 self.default_deny()
6364
64 def allow_all_incoming(self):65 def allow_all_incoming(self):
65 log("Net.allow_all_incoming")66 logging.info("Net.allow_all_incoming")
66 self.default_allow()67 self.default_allow()
6768
68 def deny_all_outgoing_except_ssh(self):69 def deny_all_outgoing_except_ssh(self):
69 log("Net.deny_all_outgoing_except_ssh")70 logging.info("Net.deny_all_outgoing_except_ssh")
70 self.allow_ssh()71 self.allow_ssh()
71 cmd = 'ufw deny out to any'72 cmd = 'ufw deny out to any'
72 run_shell_command(cmd)73 run_shell_command(cmd)
7374
74 def allow_all_outgoing(self):75 def allow_all_outgoing(self):
75 log("Net.allow_all_outgoing")76 logging.info("Net.allow_all_outgoing")
76 cmd = 'ufw delete deny out to any'77 cmd = 'ufw delete deny out to any'
77 run_shell_command(cmd)78 run_shell_command(cmd)
7879
79 def deny_port(self, port=8080):80 def deny_port(self, port=8080):
80 log("Net.deny_port port=%s" % port)81 logging.info("Net.deny_port port=%s" % port)
81 cmd = 'ufw deny ' + str(port)82 cmd = 'ufw deny ' + str(port)
82 run_shell_command(cmd)83 run_shell_command(cmd)
8384
8485
=== modified file 'runner.py'
--- runner.py 2015-04-29 19:57:39 +0000
+++ runner.py 2015-04-30 22:20:24 +0000
@@ -1,8 +1,12 @@
1from argparse import ArgumentParser1from argparse import ArgumentParser
2import logging
2from time import time3from time import time
34
4from chaos_monkey import ChaosMonkey5from chaos_monkey import ChaosMonkey
5from utility import BadRequest6from utility import (
7 BadRequest,
8 setup_logging,
9)
610
711
8def random(run_timeout, enablement_timeout):12def random(run_timeout, enablement_timeout):
@@ -35,6 +39,12 @@
35 parser.add_argument(39 parser.add_argument(
36 '-tt', '--total-timeout', default=60, type=int,40 '-tt', '--total-timeout', default=60, type=int,
37 help="Total timeout in seconds")41 help="Total timeout in seconds")
42 parser.add_argument('-lp', '--log-path', help='Where to write logs.',
43 default='log/results.log')
44 parser.add_argument('-lc', '--log-count', default=2, type=int,
45 help='The number of backups to keep.')
38 args = parser.parse_args()46 args = parser.parse_args()
47 setup_logging(log_path=args.log_path, log_count=args.log_count)
48 logging.info('Chaos monkey started')
39 random(run_timeout=args.total_timeout,49 random(run_timeout=args.total_timeout,
40 enablement_timeout=args.enablement_timeout)50 enablement_timeout=args.enablement_timeout)
4151
=== modified file 'tests/test_utility.py'
--- tests/test_utility.py 2015-04-29 19:57:39 +0000
+++ tests/test_utility.py 2015-04-30 22:20:24 +0000
@@ -1,9 +1,15 @@
1import logging
2from logging.handlers import RotatingFileHandler
1from subprocess import CalledProcessError3from subprocess import CalledProcessError
4from tempfile import NamedTemporaryFile
2from unittest import TestCase5from unittest import TestCase
36
4from mock import patch7from mock import patch
58
6from utility import run_shell_command9from utility import (
10 run_shell_command,
11 setup_logging,
12)
713
814
9class TestUtility(TestCase):15class TestUtility(TestCase):
@@ -20,3 +26,63 @@
20 def test_run_shell_command_output(self):26 def test_run_shell_command_output(self):
21 output = run_shell_command('echo "hello"')27 output = run_shell_command('echo "hello"')
22 self.assertEqual(output, '"hello"\n')28 self.assertEqual(output, '"hello"\n')
29
30 def test_setup_logging(self):
31 with NamedTemporaryFile() as temp_file:
32 setup_logging(temp_file.name, log_count=1)
33 logger = logging.getLogger()
34 self.assertEqual(logger.level, logging.DEBUG)
35 self.assertEqual(logger.name, 'root')
36 handlers = logger.handlers
37 self.assertIn(
38 type(handlers[0]), [RotatingFileHandler, logging.StreamHandler])
39 self.assertIn(
40 type(handlers[1]), [RotatingFileHandler, logging.StreamHandler])
41
42 def test_setup_logging_formatter(self):
43 log_count = 1
44 with NamedTemporaryFile() as temp_file:
45 with patch('logging.Formatter') as l_mock:
46 setup_logging(temp_file.name, log_count=log_count)
47 logger = logging.getLogger()
48 self.assertEqual(logger.name, 'root')
49 l_mock.assert_called_once_with(
50 '%(asctime)s %(levelname)s %(message)s', '%Y-%m-%d %H:%M:%S')
51
52 def test_setup_logging_rotating_file_handler(self):
53 log_count = 1
54 with NamedTemporaryFile() as temp_file:
55 with patch('utility.RotatingFileHandler') as mock:
56 setup_logging(temp_file.name, log_count=log_count)
57 mock.assert_called_once_with(
58 temp_file.name, maxBytes=1024 * 1024 * 512, backupCount=log_count)
59
60 def test_log(self):
61 with NamedTemporaryFile() as temp_file:
62 setup_logging(temp_file.name, log_count=1)
63 logging.info('testing123')
64 with open(temp_file.name, 'r') as file_reader:
65 content = file_reader.read()
66 # log format: 2015-04-29 14:03:02 INFO testing123
67 match = content.split(' ', 2)[2]
68 self.assertEqual(match, 'INFO testing123\n')
69
70 def test_log_debug(self):
71 with NamedTemporaryFile() as temp_file:
72 setup_logging(temp_file.name, log_count=1)
73 logging.debug("testing123")
74 with open(temp_file.name, 'r') as file_reader:
75 content = file_reader.read()
76 # log format: 2015-04-29 14:03:02 INFO testing123
77 match = content.split(' ', 2)[2]
78 self.assertEqual(match, 'DEBUG testing123\n')
79
80 def test_log_error(self):
81 with NamedTemporaryFile() as temp_file:
82 setup_logging(temp_file.name, log_count=1)
83 logging.error("testing123")
84 with open(temp_file.name, 'r') as file_reader:
85 content = file_reader.read()
86 # log format: 2015-04-29 14:03:02 INFO testing123
87 match = content.split(' ', 2)[2]
88 self.assertEqual(match, 'ERROR testing123\n')
2389
=== modified file 'utility.py'
--- utility.py 2015-04-29 19:57:39 +0000
+++ utility.py 2015-04-30 22:20:24 +0000
@@ -1,5 +1,8 @@
1from __future__ import print_function1from __future__ import print_function
22
3import logging
4from logging.handlers import RotatingFileHandler
5
3from subprocess import (6from subprocess import (
4 CalledProcessError,7 CalledProcessError,
5 check_output,8 check_output,
@@ -12,14 +15,25 @@
12 try:15 try:
13 output = check_output(shell_cmd)16 output = check_output(shell_cmd)
14 except CalledProcessError:17 except CalledProcessError:
15 log("Command generated error: %s " % cmd)18 logging.error("Command generated error: %s " % cmd)
16 if not quiet_mode:19 if not quiet_mode:
17 raise20 raise
18 return output21 return output
1922
2023
21def log(log_str):24def setup_logging(log_path, log_count):
22 print(log_str)25 """Install log handlers to output to file and stream."""
26 formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s',
27 '%Y-%m-%d %H:%M:%S')
28 root_logger = logging.getLogger()
29 rf_handler = RotatingFileHandler(
30 log_path, maxBytes=1024 * 1024 * 512, backupCount=log_count)
31 rf_handler.setFormatter(formatter)
32 root_logger.addHandler(rf_handler)
33 s_handler = logging.StreamHandler()
34 s_handler.setFormatter(formatter)
35 root_logger.addHandler(s_handler)
36 root_logger.setLevel(logging.DEBUG)
2337
2438
25class NotFound(Exception):39class NotFound(Exception):

Subscribers

People subscribed via source and target branches