diff --git a/swift/common/middleware/s3api/s3api.py b/swift/common/middleware/s3api/s3api.py index 23a2dc593f..5b1185e304 100644 --- a/swift/common/middleware/s3api/s3api.py +++ b/swift/common/middleware/s3api/s3api.py @@ -293,8 +293,7 @@ class S3ApiMiddleware(object): wsgi_conf.get('ratelimit_as_client_error', False)) self.logger = get_logger( - wsgi_conf, log_route=wsgi_conf.get('log_name', 's3api'), - statsd_tail_prefix='s3api') + wsgi_conf, log_route='s3api', statsd_tail_prefix='s3api') self.check_pipeline(wsgi_conf) def is_s3_cors_preflight(self, env): diff --git a/test/unit/common/middleware/s3api/test_s3api.py b/test/unit/common/middleware/s3api/test_s3api.py index ff20ea31e3..768b32f0a2 100644 --- a/test/unit/common/middleware/s3api/test_s3api.py +++ b/test/unit/common/middleware/s3api/test_s3api.py @@ -32,7 +32,7 @@ from swift.common.middleware.s3api.utils import Config from swift.common.middleware.keystoneauth import KeystoneAuth from swift.common import swob, registry from swift.common.swob import Request -from swift.common.utils import md5 +from swift.common.utils import md5, get_logger from keystonemiddleware.auth_token import AuthProtocol from keystoneauth1.access import AccessInfoV2 @@ -214,6 +214,24 @@ class TestS3ApiMiddleware(S3ApiTestCase): loader.assert_called_with(loadwsgi.APP, 'proxy-conf-file') pipeline.assert_called_with(context) + def test_init_logger(self): + proxy_logger = get_logger({}, log_route='proxy-server').logger + + s3api = S3ApiMiddleware(None, {}) + self.assertEqual('s3api', s3api.logger.name) + self.assertEqual('s3api', s3api.logger.logger.name) + self.assertIsNot(s3api.logger.logger, proxy_logger) + self.assertEqual('swift', s3api.logger.server) + self.assertIsNone(s3api.logger.logger.statsd_client) + + s3api = S3ApiMiddleware(None, {'log_name': 'proxy-server', + 'log_statsd_host': '1.2.3.4'}) + self.assertEqual('s3api', s3api.logger.name) + self.assertEqual('s3api', s3api.logger.logger.name) + self.assertIsNot(s3api.logger.logger, proxy_logger) + self.assertEqual('proxy-server', s3api.logger.server) + self.assertEqual('s3api.', s3api.logger.logger.statsd_client._prefix) + def test_non_s3_request_passthrough(self): req = Request.blank('/something') status, headers, body = self.call_s3api(req) diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index 519b34f394..8a58b66478 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -73,7 +73,8 @@ from swift.common.exceptions import Timeout, MessageTimeout, \ ConnectionTimeout, LockTimeout, ReplicationLockTimeout, \ MimeInvalid from swift.common import utils -from swift.common.utils import set_swift_dir, md5, ShardRangeList +from swift.common.utils import set_swift_dir, md5, ShardRangeList, \ + SwiftLogFormatter from swift.common.container_sync_realms import ContainerSyncRealms from swift.common.header_key_dict import HeaderKeyDict from swift.common.storage_policy import POLICIES, reload_storage_policies @@ -989,25 +990,108 @@ class TestUtils(unittest.TestCase): 'test1\ntest3\ntest4\ntest6\n') def test_get_logger_name_and_route(self): + @contextlib.contextmanager + def add_log_handler(logger): + # install a handler to capture log messages formatted as per swift + sio = StringIO() + handler = logging.StreamHandler(sio) + handler.setFormatter(SwiftLogFormatter( + fmt="%(server)s: %(message)s", max_line_length=20) + ) + logger.logger.addHandler(handler) + yield sio + logger.logger.removeHandler(handler) + logger = utils.get_logger({}, name='name', log_route='route') + # log_route becomes the LogAdapter.name and logging.Logger.name self.assertEqual('route', logger.name) + self.assertEqual('route', logger.logger.name) + # name becomes the LogAdapter.server! self.assertEqual('name', logger.server) + # LogAdapter.server is used when formatting a log message + with add_log_handler(logger) as sio: + logger.info('testing') + self.assertEqual('name: testing\n', sio.getvalue()) + logger = utils.get_logger({'log_name': 'conf-name'}, name='name', log_route='route') self.assertEqual('route', logger.name) self.assertEqual('name', logger.server) + with add_log_handler(logger) as sio: + logger.info('testing') + self.assertEqual('name: testing\n', sio.getvalue()) + logger = utils.get_logger({'log_name': 'conf-name'}, log_route='route') self.assertEqual('route', logger.name) self.assertEqual('conf-name', logger.server) + with add_log_handler(logger) as sio: + logger.info('testing') + self.assertEqual('conf-name: testing\n', sio.getvalue()) + logger = utils.get_logger({'log_name': 'conf-name'}) self.assertEqual('conf-name', logger.name) self.assertEqual('conf-name', logger.server) + with add_log_handler(logger) as sio: + logger.info('testing') + self.assertEqual('conf-name: testing\n', sio.getvalue()) + logger = utils.get_logger({}) self.assertEqual('swift', logger.name) self.assertEqual('swift', logger.server) + with add_log_handler(logger) as sio: + logger.info('testing') + self.assertEqual('swift: testing\n', sio.getvalue()) + logger = utils.get_logger({}, log_route='route') self.assertEqual('route', logger.name) self.assertEqual('swift', logger.server) + with add_log_handler(logger) as sio: + logger.info('testing') + self.assertEqual('swift: testing\n', sio.getvalue()) + + # same log_route, different names... + logger1 = utils.get_logger({'log_statsd_host': '1.2.3.4'}, + name='name1', log_route='route') + logger2 = utils.get_logger({'log_statsd_host': '1.2.3.5'}, + name='name2', log_route='route') + self.assertEqual('route', logger1.name) + self.assertEqual('route', logger1.logger.name) + self.assertEqual('name1', logger1.server) + # oh dear, the statsd client on the common logging.Logger instance got + # mutated when logger2 was created + self.assertEqual('name2.', logger1.logger.statsd_client._prefix) + self.assertEqual('route', logger2.name) + self.assertEqual('route', logger2.logger.name) + self.assertEqual('name2', logger2.server) + self.assertEqual('name2.', logger2.logger.statsd_client._prefix) + self.assertIs(logger2.logger, logger1.logger) + with add_log_handler(logger1) as sio: + logger1.info('testing') + self.assertEqual('name1: testing\n', sio.getvalue()) + with add_log_handler(logger2) as sio: + logger2.info('testing') + self.assertEqual('name2: testing\n', sio.getvalue()) + + # different log_route, different names... + logger1 = utils.get_logger({'log_statsd_host': '1.2.3.4'}, + name='name1', log_route='route1') + logger2 = utils.get_logger({'log_statsd_host': '1.2.3.5'}, + name='name2', log_route='route2') + self.assertEqual('route1', logger1.name) + self.assertEqual('route1', logger1.logger.name) + self.assertEqual('name1', logger1.server) + self.assertEqual('name1.', logger1.logger.statsd_client._prefix) + self.assertEqual('route2', logger2.name) + self.assertEqual('route2', logger2.logger.name) + self.assertEqual('name2', logger2.server) + self.assertEqual('name2.', logger2.logger.statsd_client._prefix) + self.assertIsNot(logger2.logger, logger1.logger) + with add_log_handler(logger1) as sio: + logger1.info('testing') + self.assertEqual('name1: testing\n', sio.getvalue()) + with add_log_handler(logger2) as sio: + logger2.info('testing') + self.assertEqual('name2: testing\n', sio.getvalue()) @with_tempdir def test_get_logger_sysloghandler_plumbing(self, tempdir):