From 7dc7c8af981c10b71f5072d31af25e0c81b81739 Mon Sep 17 00:00:00 2001 From: Blackoutta <37723456+Blackoutta@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:33:16 +0800 Subject: [PATCH] improve: speed up tracing config decryption process (#27549) --- api/core/ops/ops_trace_manager.py | 51 ++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/api/core/ops/ops_trace_manager.py b/api/core/ops/ops_trace_manager.py index de0d4560e3..6cc7859db7 100644 --- a/api/core/ops/ops_trace_manager.py +++ b/api/core/ops/ops_trace_manager.py @@ -14,7 +14,7 @@ from flask import current_app from sqlalchemy import select from sqlalchemy.orm import Session, sessionmaker -from core.helper.encrypter import decrypt_token, encrypt_token, obfuscated_token +from core.helper.encrypter import batch_decrypt_token, encrypt_token, obfuscated_token from core.ops.entities.config_entity import ( OPS_FILE_PATH, TracingProviderEnum, @@ -141,6 +141,8 @@ provider_config_map = OpsTraceProviderConfigMap() class OpsTraceManager: ops_trace_instances_cache: LRUCache = LRUCache(maxsize=128) + decrypted_configs_cache: LRUCache = LRUCache(maxsize=128) + _decryption_cache_lock = threading.RLock() @classmethod def encrypt_tracing_config( @@ -161,7 +163,7 @@ class OpsTraceManager: provider_config_map[tracing_provider]["other_keys"], ) - new_config = {} + new_config: dict[str, Any] = {} # Encrypt necessary keys for key in secret_keys: if key in tracing_config: @@ -191,20 +193,41 @@ class OpsTraceManager: :param tracing_config: tracing config :return: """ - config_class, secret_keys, other_keys = ( - provider_config_map[tracing_provider]["config_class"], - provider_config_map[tracing_provider]["secret_keys"], - provider_config_map[tracing_provider]["other_keys"], + config_json = json.dumps(tracing_config, sort_keys=True) + decrypted_config_key = ( + tenant_id, + tracing_provider, + config_json, ) - new_config = {} - for key in secret_keys: - if key in tracing_config: - new_config[key] = decrypt_token(tenant_id, tracing_config[key]) - for key in other_keys: - new_config[key] = tracing_config.get(key, "") + # First check without lock for performance + cached_config = cls.decrypted_configs_cache.get(decrypted_config_key) + if cached_config is not None: + return dict(cached_config) - return config_class(**new_config).model_dump() + with cls._decryption_cache_lock: + # Second check (double-checked locking) to prevent race conditions + cached_config = cls.decrypted_configs_cache.get(decrypted_config_key) + if cached_config is not None: + return dict(cached_config) + + config_class, secret_keys, other_keys = ( + provider_config_map[tracing_provider]["config_class"], + provider_config_map[tracing_provider]["secret_keys"], + provider_config_map[tracing_provider]["other_keys"], + ) + new_config: dict[str, Any] = {} + keys_to_decrypt = [key for key in secret_keys if key in tracing_config] + if keys_to_decrypt: + decrypted_values = batch_decrypt_token(tenant_id, [tracing_config[key] for key in keys_to_decrypt]) + new_config.update(zip(keys_to_decrypt, decrypted_values)) + + for key in other_keys: + new_config[key] = tracing_config.get(key, "") + + decrypted_config = config_class(**new_config).model_dump() + cls.decrypted_configs_cache[decrypted_config_key] = decrypted_config + return dict(decrypted_config) @classmethod def obfuscated_decrypt_token(cls, tracing_provider: str, decrypt_tracing_config: dict): @@ -219,7 +242,7 @@ class OpsTraceManager: provider_config_map[tracing_provider]["secret_keys"], provider_config_map[tracing_provider]["other_keys"], ) - new_config = {} + new_config: dict[str, Any] = {} for key in secret_keys: if key in decrypt_tracing_config: new_config[key] = obfuscated_token(decrypt_tracing_config[key])