diff --git a/.travis.yml b/.travis.yml
index 1273167..430b255 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,12 +2,22 @@ dist: trusty
 language: python
 python:
   - '3.6'
+env:
+  global:
+    - GIT_COMMITTED_AT=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then git log -1 --pretty=format:%ct; else git log -1 --skip 1 --pretty=format:%ct; fi)
+    - CC_TEST_REPORTER_ID=4469e75e5dc65ad713a0f9658ffbce390a68c44c0e412d921d257e0cd691e2da
 cache:
   pip: true
 install:
   - pip3 install -q -r requirements.txt -r test-requirements.txt
+before_script:
+  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > /tmp/cc-test-reporter
+  - chmod +x /tmp/cc-test-reporter
+  - /tmp/cc-test-reporter before-build
 script:
   - ./run_tests.sh
+after_script:
+  - /tmp/cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
 deploy:
   provider: pypi
   user: faucet
diff --git a/chewie/chewie.py b/chewie/chewie.py
index eff9b87..60c79f2 100644
--- a/chewie/chewie.py
+++ b/chewie/chewie.py
@@ -14,6 +14,7 @@ from chewie.radius_attributes import EAPMessage, State, CalledStationId, NASPort
 from chewie.message_parser import MessageParser, MessagePacker
 from chewie.mac_address import MacAddress
 from chewie.event import EventMessageReceived, EventRadiusMessageReceived
+from chewie.utils import get_logger
 
 
 def unpack_byte_string(byte_string):
@@ -34,7 +35,7 @@ class Chewie(object):
                  auth_handler=None, failure_handler=None, logoff_handler=None,
                  radius_server_ip=None):
         self.interface_name = interface_name
-        self.logger = logger
+        self.logger = get_logger(logger.name + "." + Chewie.__name__)
         self.auth_handler = auth_handler
         self.failure_handler = failure_handler
         self.logoff_handler = logoff_handler
@@ -226,7 +227,7 @@ class Chewie(object):
         if not sm:
             sm = FullEAPStateMachine(self.eap_output_messages, self.radius_output_messages, src_mac,
                                      self.timer_scheduler, self.auth_success,
-                                     self.auth_failure, self.auth_logoff)
+                                     self.auth_failure, self.auth_logoff, self.logger.name)
             sm.eapRestart = True
             # TODO what if port is not actually enabled, but then how did they auth?
             sm.portEnabled = True
diff --git a/chewie/eap_state_machine.py b/chewie/eap_state_machine.py
index 3bf3155..c6c3736 100644
--- a/chewie/eap_state_machine.py
+++ b/chewie/eap_state_machine.py
@@ -192,7 +192,7 @@ class FullEAPStateMachine:
     eapLogoff = None    # bool
 
     def __init__(self, eap_output_queue, radius_output_queue, src_mac, timer_scheduler,
-                 auth_handler, failure_handler, logoff_handler):
+                 auth_handler, failure_handler, logoff_handler, log_prefix):
         """
 
         Args:
@@ -219,7 +219,8 @@ class FullEAPStateMachine:
         # if we want to deal with each method locally.
         self.m = MPassthrough()
 
-        self.logger = utils.get_logger("SM - %s" % self.src_mac)
+        logname = ".SM - %s" % self.src_mac
+        self.logger = utils.get_logger(log_prefix + logname)
 
     def getId(self):
         """Determines the identifier value chosen by the AAA server for the current EAP request.
diff --git a/chewie/utils.py b/chewie/utils.py
index 002f71c..886950a 100644
--- a/chewie/utils.py
+++ b/chewie/utils.py
@@ -1,17 +1,10 @@
 """Utility Functions"""
 import logging
-import sys
 
 
-def get_logger(name, log_level=logging.DEBUG):
-    logger = logging.getLogger(name)
-    if not logger.handlers:
-        logger.setLevel(log_level)
-        ch = logging.StreamHandler(sys.stdout)
-        ch.setLevel(log_level)
-        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-        ch.setFormatter(formatter)
-        logger.addHandler(ch)
+def get_logger(logname):
+    """Create and return a logger object."""
+    logger = logging.getLogger(logname)
     return logger
 
 
diff --git a/run.py b/run.py
index 4755bb0..bf43012 100644
--- a/run.py
+++ b/run.py
@@ -1,18 +1,35 @@
+import logging
+import sys
+
 from chewie.chewie import Chewie
-import chewie.utils as utils
 
 
-credentials = {
-    "user@example.com": "microphone"
-}
+def get_logger(name, log_level=logging.DEBUG):
+    logger = logging.getLogger(name)
+    if not logger.handlers:
+        logger.setLevel(log_level)
+        ch = logging.StreamHandler(sys.stdout)
+        ch.setLevel(log_level)
+        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+        ch.setFormatter(formatter)
+        logger.addHandler(ch)
+    return logger
 
 
 def auth_handler(address, group_address):
     print("Authed address %s on port %s" % (str(address), str(group_address)))
 
 
-logger = utils.get_logger("CHEWIE")
+def failure_handler(address, group_address):
+    print("failure of address %s on port %s" % (str(address), str(group_address)))
+
+
+def logoff_handler(address, group_address):
+    print("logoff of address %s on port %s" % (str(address), str(group_address)))
+
+
+logger = get_logger("CHEWIE")
 logger.info('starting chewieeeee.')
 
-chewie = Chewie("eth1", credentials, logger, auth_handler, radius_server_ip="172.24.0.113")
+chewie = Chewie("eth1", logger, auth_handler, failure_handler, logoff_handler, radius_server_ip="172.24.0.113")
 chewie.run()

diff --git a/test/test_full_state_machine.py b/test/test_full_state_machine.py
index 5d94bb8..f49cec5 100644
--- a/test/test_full_state_machine.py
+++ b/test/test_full_state_machine.py
@@ -27,7 +27,7 @@ class FullStateMachineStartTestCase(unittest.TestCase):
         self.src_mac = MacAddress.from_string("00:12:34:56:78:90")
         self.sm = FullEAPStateMachine(self.eap_output_queue, self.radius_output_queue, self.src_mac,
                                       self.timer_scheduler,
-                                      self.auth_handler, self.failure_handler, self.logoff_handler)
+                                      self.auth_handler, self.failure_handler, self.logoff_handler, 'Chewie')
         self.MAX_RETRANSMITS = 3
         self.sm.MAX_RETRANS = self.MAX_RETRANSMITS
         self.sm.DEFAULT_TIMEOUT = 0.1

Statemachine logging isn't working with Faucet
Investigate. It is working when running standalone.
test/test_full_state_machine.py::FullStateMachineStartTestCase::test_disabled_state test/test_full_state_machine.py::FullStateMachineStartTestCase::test_discard test/test_full_state_machine.py::FullStateMachineStartTestCase::test_discard2 test/test_full_state_machine.py::FullStateMachineStartTestCase::test_eap_restart test/test_full_state_machine.py::FullStateMachineStartTestCase::test_eap_start test/test_full_state_machine.py::FullStateMachineStartTestCase::test_failure2 test/test_full_state_machine.py::FullStateMachineStartTestCase::test_identity_response test/test_full_state_machine.py::FullStateMachineStartTestCase::test_logoff2 test/test_full_state_machine.py::FullStateMachineStartTestCase::test_logoff_from_idle2 test/test_full_state_machine.py::FullStateMachineStartTestCase::test_md5_challenge_request test/test_full_state_machine.py::FullStateMachineStartTestCase::test_md5_challenge_response test/test_full_state_machine.py::FullStateMachineStartTestCase::test_success2 test/test_full_state_machine.py::FullStateMachineStartTestCase::test_timeout_failure2_from_aaa_timeout test/test_full_state_machine.py::FullStateMachineStartTestCase::test_timeout_failure2_from_max_retransmits test/test_full_state_machine.py::FullStateMachineStartTestCase::test_timeout_failure_from_max_retransmits test/test_full_state_machine.py::FullStateMachineStartTestCase::test_ttls_request