Adding domain to context and log

Add support for upcoming "domain" concept in Keystone V3 API in
both logging and context.

Closes-Bug: #1248936
Implements: blueprint add-domain-info-to-context
Change-Id: Ic2cf3e52cfcc0b8adccdf9c59afaa4014708a303
This commit is contained in:
Davanum Srinivas 2013-11-11 20:19:32 -05:00 committed by Demontiê Junior
parent 9feea9c15e
commit c50d3d633b
3 changed files with 62 additions and 6 deletions

View File

@ -36,12 +36,18 @@ class RequestContext(object):
accesses the system, as well as additional request information. accesses the system, as well as additional request information.
""" """
def __init__(self, auth_token=None, user=None, tenant=None, is_admin=False, user_idt_format = '{user} {tenant} {domain} {user_domain} {p_domain}'
def __init__(self, auth_token=None, user=None, tenant=None, domain=None,
user_domain=None, project_domain=None, is_admin=False,
read_only=False, show_deleted=False, request_id=None, read_only=False, show_deleted=False, request_id=None,
instance_uuid=None): instance_uuid=None):
self.auth_token = auth_token self.auth_token = auth_token
self.user = user self.user = user
self.tenant = tenant self.tenant = tenant
self.domain = domain
self.user_domain = user_domain
self.project_domain = project_domain
self.is_admin = is_admin self.is_admin = is_admin
self.read_only = read_only self.read_only = read_only
self.show_deleted = show_deleted self.show_deleted = show_deleted
@ -51,14 +57,25 @@ class RequestContext(object):
self.request_id = request_id self.request_id = request_id
def to_dict(self): def to_dict(self):
user_idt = (
self.user_idt_format.format(user=self.user or '-',
tenant=self.tenant or '-',
domain=self.domain or '-',
user_domain=self.user_domain or '-',
p_domain=self.project_domain or '-'))
return {'user': self.user, return {'user': self.user,
'tenant': self.tenant, 'tenant': self.tenant,
'domain': self.domain,
'user_domain': self.user_domain,
'project_domain': self.project_domain,
'is_admin': self.is_admin, 'is_admin': self.is_admin,
'read_only': self.read_only, 'read_only': self.read_only,
'show_deleted': self.show_deleted, 'show_deleted': self.show_deleted,
'auth_token': self.auth_token, 'auth_token': self.auth_token,
'request_id': self.request_id, 'request_id': self.request_id,
'instance_uuid': self.instance_uuid} 'instance_uuid': self.instance_uuid,
'user_identity': user_idt}
def get_admin_context(show_deleted=False): def get_admin_context(show_deleted=False):

View File

@ -130,7 +130,7 @@ generic_log_opts = [
log_opts = [ log_opts = [
cfg.StrOpt('logging_context_format_string', cfg.StrOpt('logging_context_format_string',
default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
'%(name)s [%(request_id)s %(user)s %(tenant)s] ' '%(name)s [%(request_id)s %(user_identity)s] '
'%(instance)s%(message)s', '%(instance)s%(message)s',
help='format string to use for log messages with context'), help='format string to use for log messages with context'),
cfg.StrOpt('logging_default_format_string', cfg.StrOpt('logging_default_format_string',
@ -332,10 +332,12 @@ class ContextAdapter(BaseLoggerAdapter):
elif instance_uuid: elif instance_uuid:
instance_extra = (CONF.instance_uuid_format instance_extra = (CONF.instance_uuid_format
% {'uuid': instance_uuid}) % {'uuid': instance_uuid})
extra.update({'instance': instance_extra}) extra['instance'] = instance_extra
extra.update({"project": self.project}) extra.setdefault('user_identity', kwargs.pop('user_identity', None))
extra.update({"version": self.version})
extra['project'] = self.project
extra['version'] = self.version
extra['extra'] = extra.copy() extra['extra'] = extra.copy()
return msg, kwargs return msg, kwargs

View File

@ -370,6 +370,43 @@ class FancyRecordTestCase(test.BaseTestCase):
(ctxt.request_id, ctxt.instance_uuid))) (ctxt.request_id, ctxt.instance_uuid)))
class DomainTestCase(test.BaseTestCase):
def setUp(self):
super(DomainTestCase, self).setUp()
self.config = self.useFixture(config.Config()).config
self.config(logging_context_format_string="[%(request_id)s]: "
"%(user_identity)s "
"%(message)s")
self.mylog = log.getLogger()
self.stream = six.StringIO()
handler = logging.StreamHandler(self.stream)
handler.setFormatter(log.ContextFormatter())
self.mylog.logger.addHandler(handler)
self.mylog.logger.setLevel(logging.DEBUG)
def _validate_keys(self, ctxt, keyed_log_string):
infoexpected = "%s info\n" % (keyed_log_string)
warnexpected = "%s warn\n" % (keyed_log_string)
self.mylog.info("info", context=ctxt)
self.assertEqual(infoexpected, self.stream.getvalue())
self.mylog.warn("warn", context=ctxt)
self.assertEqual(infoexpected + warnexpected, self.stream.getvalue())
def test_domain_in_log_msg(self):
ctxt = _fake_context()
ctxt.domain = 'mydomain'
ctxt.project_domain = 'myprojectdomain'
ctxt.user_domain = 'myuserdomain'
user_identity = ctxt.to_dict()['user_identity']
self.assertTrue(ctxt.domain in user_identity)
self.assertTrue(ctxt.project_domain in user_identity)
self.assertTrue(ctxt.user_domain in user_identity)
self._validate_keys(ctxt, ('[%s]: %s' %
(ctxt.request_id, user_identity)))
class SetDefaultsTestCase(test.BaseTestCase): class SetDefaultsTestCase(test.BaseTestCase):
class TestConfigOpts(cfg.ConfigOpts): class TestConfigOpts(cfg.ConfigOpts):
def __call__(self, args=None): def __call__(self, args=None):