policies: optimise logging

This commit is contained in:
Jens Langhammer 2021-02-02 15:50:42 +01:00
parent 4d7e64c48c
commit 624206281e
7 changed files with 14 additions and 34 deletions

View file

@ -4,9 +4,6 @@ from django.apps import AppConfig, apps
from django.contrib import admin from django.contrib import admin
from django.contrib.admin.sites import AlreadyRegistered from django.contrib.admin.sites import AlreadyRegistered
from guardian.admin import GuardedModelAdmin from guardian.admin import GuardedModelAdmin
from structlog.stdlib import get_logger
LOGGER = get_logger()
def admin_autoregister(app: AppConfig): def admin_autoregister(app: AppConfig):
@ -20,5 +17,4 @@ def admin_autoregister(app: AppConfig):
for _app in apps.get_app_configs(): for _app in apps.get_app_configs():
if _app.label.startswith("authentik_"): if _app.label.startswith("authentik_"):
LOGGER.debug("Registering application for dj-admin", application=_app.label)
admin_autoregister(_app) admin_autoregister(_app)

View file

@ -1,7 +1,6 @@
"""logging helpers""" """logging helpers"""
from logging import Logger from logging import Logger
from os import getpid from os import getpid
from typing import Callable
# pylint: disable=unused-argument # pylint: disable=unused-argument
@ -9,15 +8,3 @@ def add_process_id(logger: Logger, method_name: str, event_dict):
"""Add the current process ID""" """Add the current process ID"""
event_dict["pid"] = getpid() event_dict["pid"] = getpid()
return event_dict return event_dict
def add_common_fields(environment: str) -> Callable:
"""Add a common field to easily search for authentik logs"""
def add_common_field(logger: Logger, method_name: str, event_dict):
"""Add a common field to easily search for authentik logs"""
event_dict["app"] = "authentik"
event_dict["app_environment"] = environment
return event_dict
return add_common_field

View file

@ -59,6 +59,5 @@ def before_send(event, hint):
if "exc_info" in hint: if "exc_info" in hint:
_, exc_value, _ = hint["exc_info"] _, exc_value, _ = hint["exc_info"]
if isinstance(exc_value, ignored_classes): if isinstance(exc_value, ignored_classes):
LOGGER.info("Supressing error %r", exc_value)
return None return None
return event return event

View file

@ -8,14 +8,13 @@ from django.core.cache import cache
from django.http import HttpRequest from django.http import HttpRequest
from sentry_sdk.hub import Hub from sentry_sdk.hub import Hub
from sentry_sdk.tracing import Span from sentry_sdk.tracing import Span
from structlog.stdlib import get_logger from structlog.stdlib import BoundLogger, get_logger
from authentik.core.models import User from authentik.core.models import User
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel
from authentik.policies.process import PolicyProcess, cache_key from authentik.policies.process import PolicyProcess, cache_key
from authentik.policies.types import PolicyRequest, PolicyResult from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger()
CURRENT_PROCESS = current_process() CURRENT_PROCESS = current_process()
@ -49,6 +48,7 @@ class PolicyEngine:
use_cache: bool use_cache: bool
request: PolicyRequest request: PolicyRequest
logger: BoundLogger
mode: PolicyEngineMode mode: PolicyEngineMode
# Allow objects with no policies attached to pass # Allow objects with no policies attached to pass
empty_result: bool empty_result: bool
@ -62,6 +62,7 @@ class PolicyEngine:
def __init__( def __init__(
self, pbm: PolicyBindingModel, user: User, request: HttpRequest = None self, pbm: PolicyBindingModel, user: User, request: HttpRequest = None
): ):
self.logger = get_logger().bind()
self.mode = PolicyEngineMode.MODE_AND self.mode = PolicyEngineMode.MODE_AND
# For backwards compatibility, set empty_result to true # For backwards compatibility, set empty_result to true
# objects with no policies attached will pass. # objects with no policies attached will pass.
@ -105,18 +106,18 @@ class PolicyEngine:
key = cache_key(binding, self.request) key = cache_key(binding, self.request)
cached_policy = cache.get(key, None) cached_policy = cache.get(key, None)
if cached_policy and self.use_cache: if cached_policy and self.use_cache:
LOGGER.debug( self.logger.debug(
"P_ENG: Taking result from cache", "P_ENG: Taking result from cache",
policy=binding.policy, policy=binding.policy,
cache_key=key, cache_key=key,
) )
self.__cached_policies.append(cached_policy) self.__cached_policies.append(cached_policy)
continue continue
LOGGER.debug("P_ENG: Evaluating policy", policy=binding.policy) self.logger.debug("P_ENG: Evaluating policy", policy=binding.policy)
our_end, task_end = Pipe(False) our_end, task_end = Pipe(False)
task = PolicyProcess(binding, self.request, task_end) task = PolicyProcess(binding, self.request, task_end)
task.daemon = False task.daemon = False
LOGGER.debug("P_ENG: Starting Process", policy=binding.policy) self.logger.debug("P_ENG: Starting Process", policy=binding.policy)
if not CURRENT_PROCESS._config.get("daemon"): if not CURRENT_PROCESS._config.get("daemon"):
task.run() task.run()
else: else:

View file

@ -17,6 +17,9 @@ from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger() LOGGER = get_logger()
TRACEBACK_HEADER = "Traceback (most recent call last):\n" TRACEBACK_HEADER = "Traceback (most recent call last):\n"
FORK_CTX = get_context("fork")
PROCESS_CLASS = FORK_CTX.Process
def cache_key(binding: PolicyBinding, request: PolicyRequest) -> str: def cache_key(binding: PolicyBinding, request: PolicyRequest) -> str:
"""Generate Cache key for policy""" """Generate Cache key for policy"""
@ -28,10 +31,6 @@ def cache_key(binding: PolicyBinding, request: PolicyRequest) -> str:
return prefix return prefix
FORK_CTX = get_context("fork")
PROCESS_CLASS = FORK_CTX.Process
class PolicyProcess(PROCESS_CLASS): class PolicyProcess(PROCESS_CLASS):
"""Evaluate a single policy within a seprate process""" """Evaluate a single policy within a seprate process"""
@ -103,17 +102,16 @@ class PolicyProcess(PROCESS_CLASS):
# Invert result if policy.negate is set # Invert result if policy.negate is set
if self.binding.negate: if self.binding.negate:
policy_result.passing = not policy_result.passing policy_result.passing = not policy_result.passing
key = cache_key(self.binding, self.request)
cache.set(key, policy_result)
LOGGER.debug( LOGGER.debug(
"P_ENG(proc): Finished", "P_ENG(proc): finished and cached ",
policy=self.binding.policy, policy=self.binding.policy,
result=policy_result, result=policy_result,
process="PolicyProcess", process="PolicyProcess",
passing=policy_result.passing, passing=policy_result.passing,
user=self.request.user, user=self.request.user,
) )
key = cache_key(self.binding, self.request)
cache.set(key, policy_result)
LOGGER.debug("P_ENG(proc): Cached policy evaluation", key=key)
return policy_result return policy_result
def run(self): # pragma: no cover def run(self): # pragma: no cover

View file

@ -27,7 +27,7 @@ from sentry_sdk.integrations.redis import RedisIntegration
from authentik import __version__ from authentik import __version__
from authentik.core.middleware import structlog_add_request_id from authentik.core.middleware import structlog_add_request_id
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.logging import add_common_fields, add_process_id from authentik.lib.logging import add_process_id
from authentik.lib.sentry import before_send from authentik.lib.sentry import before_send
@ -363,7 +363,6 @@ structlog.configure_once(
structlog.stdlib.add_logger_name, structlog.stdlib.add_logger_name,
structlog.threadlocal.merge_threadlocal_context, structlog.threadlocal.merge_threadlocal_context,
add_process_id, add_process_id,
add_common_fields(CONFIG.y("error_reporting.environment", "customer")),
structlog_add_request_id, structlog_add_request_id,
structlog.stdlib.PositionalArgumentsFormatter(), structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso", utc=False), structlog.processors.TimeStamper(fmt="iso", utc=False),

View file

@ -50,7 +50,7 @@ for _authentik_app in get_apps():
LOGGER.debug( LOGGER.debug(
"Mounted URLs", "Mounted URLs",
app_name=_authentik_app.name, app_name=_authentik_app.name,
mountpoint=mountpoint, app_mountpoint=mountpoint,
namespace=namespace, namespace=namespace,
) )