logger: migrate belief_scope from legacy markers to molecular CoT protocol

Replace [Entry]/[Exit]/[Action]/[COHERENCE:OK] with [REASON]/[REFLECT]/[EXPLORE]
in belief_scope context manager, BeliefFormatter, and 34 source files.
Per molecular-cot-logging skill invariants.
This commit is contained in:
2026-05-13 08:46:24 +03:00
parent 306c5ae742
commit b6f46fe9f5
30 changed files with 149 additions and 153 deletions

View File

@@ -311,7 +311,7 @@ async def list_permissions(
)
if inserted_count > 0:
logger.info(
"[api.admin.list_permissions][Action] Synchronized %s missing RBAC permissions into auth catalog",
"[api.admin.list_permissions][REASON] Synchronized %s missing RBAC permissions into auth catalog",
inserted_count,
)

View File

@@ -184,7 +184,7 @@ async def get_dashboards(
total_pages = page_payload["total_pages"]
except Exception as page_error:
logger.warning(
"[get_dashboards][Action] Page-based fetch failed; using compatibility fallback: %s",
"[get_dashboards][REASON] Page-based fetch failed; using compatibility fallback: %s",
page_error,
)
if can_apply_slug_filter:

View File

@@ -62,7 +62,7 @@ def _resolve_repository_status(dashboard_id: int) -> dict:
repo_path = git_service._get_repo_path(dashboard_id)
if not os.path.exists(repo_path):
logger.debug(
f"[get_repository_status][Action] Repository is not initialized for dashboard {dashboard_id}"
f"[get_repository_status][REASON] Repository is not initialized for dashboard {dashboard_id}"
)
return _build_no_repo_status_payload()
@@ -71,7 +71,7 @@ def _resolve_repository_status(dashboard_id: int) -> dict:
except HTTPException as e:
if e.status_code == 404:
logger.debug(
f"[get_repository_status][Action] Repository is not initialized for dashboard {dashboard_id}"
f"[get_repository_status][REASON] Repository is not initialized for dashboard {dashboard_id}"
)
return _build_no_repo_status_payload()
raise
@@ -288,7 +288,7 @@ def _resolve_current_user_git_identity(
)
except Exception as resolve_error:
logger.warning(
"[_resolve_current_user_git_identity][Action] Failed to load profile preference for user %s: %s",
"[_resolve_current_user_git_identity][REASON] Failed to load profile preference for user %s: %s",
user_id,
resolve_error,
)

View File

@@ -129,12 +129,12 @@ async def pull_changes(
config_provider = config_row.provider
except Exception as diagnostics_error:
logger.warning(
"[pull_changes][Action] Failed to load repository binding diagnostics for dashboard %s: %s",
"[pull_changes][REASON] Failed to load repository binding diagnostics for dashboard %s: %s",
dashboard_id,
diagnostics_error,
)
logger.info(
"[pull_changes][Action] Route diagnostics dashboard_ref=%s env_id=%s resolved_dashboard_id=%s "
"[pull_changes][REASON] Route diagnostics dashboard_ref=%s env_id=%s resolved_dashboard_id=%s "
"binding_exists=%s binding_local_path=%s binding_remote_url=%s binding_config_id=%s config_provider=%s config_url=%s",
dashboard_ref,
env_id,
@@ -191,7 +191,7 @@ async def get_repository_status_batch(
dashboard_ids = list(dict.fromkeys(request.dashboard_ids))
if len(dashboard_ids) > MAX_REPOSITORY_STATUS_BATCH:
logger.warning(
"[get_repository_status_batch][Action] Batch size %s exceeds limit %s. Truncating request.",
"[get_repository_status_batch][REASON] Batch size %s exceeds limit %s. Truncating request.",
len(dashboard_ids),
MAX_REPOSITORY_STATUS_BATCH,
)

View File

@@ -62,7 +62,7 @@ async def init_repository(
try:
logger.info(
f"[init_repository][Action] Initializing repo for dashboard {dashboard_id}"
f"[init_repository][REASON] Initializing repo for dashboard {dashboard_id}"
)
_gs.init_repo(
dashboard_id,

View File

@@ -53,7 +53,7 @@ async def get_providers(
Get all LLM provider configurations.
"""
logger.info(
f"[llm_routes][get_providers][Action] Fetching providers for user: {current_user.username}"
f"[llm_routes][get_providers][REASON] Fetching providers for user: {current_user.username}"
)
service = LLMProviderService(db)
providers = service.get_all_providers()
@@ -249,7 +249,7 @@ async def test_connection(
db: Session = Depends(get_db),
):
logger.info(
f"[llm_routes][test_connection][Action] Testing connection for provider_id: {provider_id}"
f"[llm_routes][test_connection][REASON] Testing connection for provider_id: {provider_id}"
)
"""
Test connection to an LLM provider.
@@ -306,7 +306,7 @@ async def test_provider_config(
from ...plugins.llm_analysis.service import LLMClient
logger.info(
f"[llm_routes][test_provider_config][Action] Testing config for {config.name}"
f"[llm_routes][test_provider_config][REASON] Testing config for {config.name}"
)
# Check if API key is provided

View File

@@ -358,7 +358,7 @@ async def trigger_sync_now(
)
db.add(db_env)
logger.info(
f"[trigger_sync_now][Action] Created environment row for {env.id}"
f"[trigger_sync_now][REASON] Created environment row for {env.id}"
)
else:
existing.name = env.name
@@ -373,7 +373,7 @@ async def trigger_sync_now(
client = SupersetClient(env)
service.sync_environment(env.id, client)
results["synced"].append(env.id)
logger.info(f"[trigger_sync_now][Action] Synced environment {env.id}")
logger.info(f"[trigger_sync_now][REASON] Synced environment {env.id}")
except Exception as e:
results["failed"].append({"env_id": env.id, "error": str(e)})
logger.error(f"[trigger_sync_now][Error] Failed to sync {env.id}: {e}")

View File

@@ -88,7 +88,7 @@ async def get_settings(
_=Depends(has_permission("admin:settings", "READ")),
):
with belief_scope("get_settings"):
logger.info("[get_settings][Entry] Fetching all settings")
logger.info("[get_settings][REASON] Fetching all settings")
config = config_manager.get_config().copy(deep=True)
config.settings.llm = normalize_llm_settings(config.settings.llm)
# Mask passwords
@@ -127,7 +127,7 @@ async def update_global_settings(
_=Depends(has_permission("admin:settings", "WRITE")),
):
with belief_scope("update_global_settings"):
logger.info("[update_global_settings][Entry] Updating global settings")
logger.info("[update_global_settings][REASON] Updating global settings")
config_manager.update_global_settings(settings)
return settings
@@ -183,7 +183,7 @@ async def get_environments(
_=Depends(has_permission("admin:settings", "READ")),
):
with belief_scope("get_environments"):
logger.info("[get_environments][Entry] Fetching environments")
logger.info("[get_environments][REASON] Fetching environments")
environments = config_manager.get_environments()
return [
env.copy(update={"url": _normalize_superset_env_url(env.url)})
@@ -205,7 +205,7 @@ async def add_environment(
_=Depends(has_permission("admin:settings", "WRITE")),
):
with belief_scope("add_environment"):
logger.info(f"[add_environment][Entry] Adding environment {env.id}")
logger.info(f"[add_environment][REASON] Adding environment {env.id}")
env = env.copy(update={"url": _normalize_superset_env_url(env.url)})
# Validate connection before adding (fast path)
@@ -237,7 +237,7 @@ async def update_environment(
config_manager: ConfigManager = Depends(get_config_manager),
):
with belief_scope("update_environment"):
logger.info(f"[update_environment][Entry] Updating environment {id}")
logger.info(f"[update_environment][REASON] Updating environment {id}")
env = env.copy(update={"url": _normalize_superset_env_url(env.url)})
@@ -278,7 +278,7 @@ async def delete_environment(
id: str, config_manager: ConfigManager = Depends(get_config_manager)
):
with belief_scope("delete_environment"):
logger.info(f"[delete_environment][Entry] Deleting environment {id}")
logger.info(f"[delete_environment][REASON] Deleting environment {id}")
config_manager.delete_environment(id)
return {"message": f"Environment {id} deleted"}
@@ -295,7 +295,7 @@ async def test_environment_connection(
id: str, config_manager: ConfigManager = Depends(get_config_manager)
):
with belief_scope("test_environment_connection"):
logger.info(f"[test_environment_connection][Entry] Testing environment {id}")
logger.info(f"[test_environment_connection][REASON] Testing environment {id}")
# Find environment
env = next((e for e in config_manager.get_environments() if e.id == id), None)
@@ -352,7 +352,7 @@ async def update_logging_config(
):
with belief_scope("update_logging_config"):
logger.info(
f"[update_logging_config][Entry] Updating logging config: level={config.level}, task_log_level={config.task_log_level}"
f"[update_logging_config][REASON] Updating logging config: level={config.level}, task_log_level={config.task_log_level}"
)
# Get current settings and update logging config
@@ -476,7 +476,7 @@ async def update_consolidated_settings(
):
with belief_scope("update_consolidated_settings"):
logger.info(
"[update_consolidated_settings][Entry] Applying consolidated settings patch"
"[update_consolidated_settings][REASON] Applying consolidated settings patch"
)
current_config = config_manager.get_config()

View File

@@ -27,16 +27,16 @@ class BeliefFormatter(logging.Formatter):
# [DEF:format:Function]
# @PURPOSE: Formats the log record, adding belief state context if available.
# @PRE: record is a logging.LogRecord.
# @POST: Returns formatted string.
# @POST: Returns formatted string with molecular CoT markers.
# @PARAM: record (logging.LogRecord) - The log record to format.
# @RETURN: str - The formatted log message.
# @SEMANTICS: logging, formatter, context
# @SEMANTICS: logging, formatter, context, cot
def format(self, record):
anchor_id = getattr(_belief_state, 'anchor_id', None)
if anchor_id:
msg = str(record.msg)
# Supported molecular topology markers
markers = ("[EXPLORE]", "[REASON]", "[REFLECT]", "[COHERENCE:", "[Action]", "[Entry]", "[Exit]")
# Molecular CoT topology markers only (REASON | REFLECT | EXPLORE)
markers = ("[EXPLORE]", "[REASON]", "[REFLECT]")
# Avoid duplicating anchor or overriding explicit markers
if msg.startswith(f"[{anchor_id}]"):
@@ -44,8 +44,8 @@ class BeliefFormatter(logging.Formatter):
elif any(msg.startswith(m) for m in markers):
record.msg = f"[{anchor_id}]{msg}"
else:
# Default covalent bond
record.msg = f"[{anchor_id}][Action] {msg}"
# Default molecular bond
record.msg = f"[{anchor_id}][REASON] {msg}"
return super().format(record)
# [/DEF:format:Function]
@@ -62,32 +62,28 @@ class LogEntry(BaseModel):
# #endregion LogEntry
# #region belief_scope [TYPE Function] [SEMANTICS logging, context, belief_state]
# @BRIEF Context manager for structured Belief State logging.
# #region belief_scope [TYPE Function] [SEMANTICS logging, context, belief_state, cot]
# @BRIEF Context manager for Molecular CoT structured logging.
# @PRE: anchor_id must be provided.
# @POST: Thread-local belief state is updated and entry/exit logs are generated.
# @POST: Thread-local belief state is updated; REASON/REFLECT/EXPLORE markers emitted.
@contextmanager
def belief_scope(anchor_id: str, message: str = ""):
# Log Entry if enabled (DEBUG level to reduce noise)
if _enable_belief_state:
entry_msg = f"[{anchor_id}][Entry]"
if message:
entry_msg += f" {message}"
logger.debug(entry_msg)
# Set thread-local anchor_id
# Set thread-local anchor_id FIRST so BeliefFormatter can apply prefix
old_anchor = getattr(_belief_state, 'anchor_id', None)
_belief_state.anchor_id = anchor_id
try:
yield
# Log Coherence OK and Exit (DEBUG level to reduce noise)
logger.debug("[COHERENCE:OK]")
# Log entry as REASON (deep-reasoning bond)
if _enable_belief_state:
logger.debug("[Exit]")
intent_msg = message or f"Entering {anchor_id}"
logger.reason(intent_msg)
yield
# Log success as REFLECT (self-reflection bond)
logger.reflect(f"Completed successfully — {message or 'no message'}")
except Exception as e:
# Log Coherence Failed (DEBUG level to reduce noise)
logger.debug(f"[COHERENCE:FAILED] {str(e)}")
# Log exception as EXPLORE (self-exploration bond)
logger.explore(f"Assumption violated — {str(e)}")
raise
finally:
# Restore old anchor

View File

@@ -43,13 +43,13 @@ def reset_logger_state():
configure_logger(config)
# [DEF:test_belief_scope_logs_entry_action_exit_at_debug:Function]
# [DEF:test_belief_scope_logs_reason_reflect_at_debug:Function]
# @RELATION: BINDS_TO -> test_logger
# @PURPOSE: Test that belief_scope generates [ID][Entry], [ID][Action], and [ID][Exit] logs at DEBUG level.
# @PURPOSE: Test that belief_scope generates [REASON] and [REFLECT] logs at DEBUG level.
# @PRE: belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
# @POST: Logs are verified to contain Entry, Action, and Exit tags at DEBUG level.
def test_belief_scope_logs_entry_action_exit_at_debug(caplog):
"""Test that belief_scope generates [ID][Entry], [ID][Action], and [ID][Exit] logs at DEBUG level."""
# @POST: Logs are verified to contain REASON and REFLECT markers at DEBUG level.
def test_belief_scope_logs_reason_reflect_at_debug(caplog):
"""Test that belief_scope generates [REASON] and [REFLECT] logs at DEBUG level."""
# Configure logger to DEBUG level
config = LoggingConfig(
level="DEBUG",
@@ -66,23 +66,23 @@ def test_belief_scope_logs_entry_action_exit_at_debug(caplog):
# Check that the logs contain the expected patterns
log_messages = [record.message for record in caplog.records]
assert any("[TestFunction][Entry]" in msg for msg in log_messages), "Entry log not found"
assert any("[TestFunction][Action] Doing something important" in msg for msg in log_messages), "Action log not found"
assert any("[TestFunction][Exit]" in msg for msg in log_messages), "Exit log not found"
assert any("[REASON]" in msg and "TestFunction" in msg for msg in log_messages), "REASON log not found"
assert any("Doing something important" in msg for msg in log_messages), "Inline info log not found"
assert any("[REFLECT]" in msg and "TestFunction" in msg for msg in log_messages), "REFLECT log not found"
# Reset to INFO
config = LoggingConfig(level="INFO", task_log_level="INFO", enable_belief_state=True)
configure_logger(config)
# [/DEF:test_belief_scope_logs_entry_action_exit_at_debug:Function]
# [/DEF:test_belief_scope_logs_reason_reflect_at_debug:Function]
# [DEF:test_belief_scope_error_handling:Function]
# @RELATION: BINDS_TO -> test_logger
# @PURPOSE: Test that belief_scope logs Coherence:Failed on exception.
# @PURPOSE: Test that belief_scope logs EXPLORE on exception.
# @PRE: belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
# @POST: Logs are verified to contain Coherence:Failed tag.
# @POST: Logs are verified to contain EXPLORE marker.
def test_belief_scope_error_handling(caplog):
"""Test that belief_scope logs Coherence:Failed on exception."""
"""Test that belief_scope logs EXPLORE on exception."""
# Configure logger to DEBUG level
config = LoggingConfig(
level="DEBUG",
@@ -99,9 +99,10 @@ def test_belief_scope_error_handling(caplog):
log_messages = [record.message for record in caplog.records]
assert any("[FailingFunction][Entry]" in msg for msg in log_messages), "Entry log not found"
assert any("[FailingFunction][COHERENCE:FAILED]" in msg for msg in log_messages), "Failed coherence log not found"
# Exit should not be logged on failure
assert any("[REASON]" in msg and "FailingFunction" in msg for msg in log_messages), "REASON log not found"
assert any("[EXPLORE]" in msg and "FailingFunction" in msg and "Something went wrong" in msg
for msg in log_messages), "EXPLORE log not found"
# REFLECT should not be logged on failure
# Reset to INFO
config = LoggingConfig(level="INFO", task_log_level="INFO", enable_belief_state=True)
@@ -109,13 +110,13 @@ def test_belief_scope_error_handling(caplog):
# [/DEF:test_belief_scope_error_handling:Function]
# [DEF:test_belief_scope_success_coherence:Function]
# [DEF:test_belief_scope_success_reflect:Function]
# @RELATION: BINDS_TO -> test_logger
# @PURPOSE: Test that belief_scope logs Coherence:OK on success.
# @PURPOSE: Test that belief_scope logs REFLECT on success.
# @PRE: belief_scope is available. caplog fixture is used. Logger configured to DEBUG.
# @POST: Logs are verified to contain Coherence:OK tag.
def test_belief_scope_success_coherence(caplog):
"""Test that belief_scope logs Coherence:OK on success."""
# @POST: Logs are verified to contain REFLECT marker.
def test_belief_scope_success_reflect(caplog):
"""Test that belief_scope logs REFLECT on success."""
# Configure logger to DEBUG level
config = LoggingConfig(
level="DEBUG",
@@ -131,19 +132,19 @@ def test_belief_scope_success_coherence(caplog):
log_messages = [record.message for record in caplog.records]
assert any("[SuccessFunction][COHERENCE:OK]" in msg for msg in log_messages), "Success coherence log not found"
assert any("[REFLECT]" in msg and "SuccessFunction" in msg for msg in log_messages), "REFLECT log not found"
# [/DEF:test_belief_scope_success_coherence:Function]
# [/DEF:test_belief_scope_success_reflect:Function]
# [DEF:test_belief_scope_not_visible_at_info:Function]
# @RELATION: BINDS_TO -> test_logger
# @PURPOSE: Test that belief_scope Entry/Exit/Coherence logs are NOT visible at INFO level.
# @PURPOSE: Test that belief_scope REFLECT logs are NOT visible at INFO level.
# @PRE: belief_scope is available. caplog fixture is used.
# @POST: Entry/Exit/Coherence logs are not captured at INFO level.
# @POST: REASON is visible at INFO (uses info()); REFLECT is not (uses debug()).
def test_belief_scope_not_visible_at_info(caplog):
"""Test that belief_scope Entry/Exit/Coherence logs are NOT visible at INFO level."""
"""Test that belief_scope REFLECT logs are NOT visible at INFO level."""
caplog.set_level("INFO")
with belief_scope("InfoLevelFunction"):
@@ -151,12 +152,12 @@ def test_belief_scope_not_visible_at_info(caplog):
log_messages = [record.message for record in caplog.records]
# Action log should be visible
assert any("[InfoLevelFunction][Action] Doing something important" in msg for msg in log_messages), "Action log not found"
# Entry/Exit/Coherence should NOT be visible at INFO level
assert not any("[InfoLevelFunction][Entry]" in msg for msg in log_messages), "Entry log should not be visible at INFO"
assert not any("[InfoLevelFunction][Exit]" in msg for msg in log_messages), "Exit log should not be visible at INFO"
assert not any("[InfoLevelFunction][COHERENCE:OK]" in msg for msg in log_messages), "Coherence log should not be visible at INFO"
# Inline INFO log should be visible
assert any("Doing something important" in msg for msg in log_messages), "INFO log not found"
# REASON uses info() → visible at INFO level
assert any("[REASON]" in msg and "InfoLevelFunction" in msg for msg in log_messages), "REASON log should be visible at INFO"
# REFLECT uses debug() → NOT visible at INFO level
assert not any("[REFLECT]" in msg for msg in log_messages), "REFLECT log should not be visible at INFO"
# [/DEF:test_belief_scope_not_visible_at_info:Function]
@@ -210,9 +211,9 @@ def test_configure_logger_task_log_level():
# @RELATION: BINDS_TO -> test_logger
# @PURPOSE: Test that enable_belief_state flag controls belief_scope logging.
# @PRE: LoggingConfig is available. caplog fixture is used.
# @POST: belief_scope logs are controlled by the flag.
# @POST: belief_scope explicit REASON logs are controlled by the flag; REFLECT always logged.
def test_enable_belief_state_flag(caplog):
"""Test that enable_belief_state flag controls belief_scope logging."""
"""Test that enable_belief_state flag controls belief_scope REASON entry logging."""
# Disable belief state
config = LoggingConfig(
level="DEBUG",
@@ -228,11 +229,10 @@ def test_enable_belief_state_flag(caplog):
log_messages = [record.message for record in caplog.records]
# Entry and Exit should NOT be logged when disabled
assert not any("[DisabledFunction][Entry]" in msg for msg in log_messages), "Entry should not be logged when disabled"
assert not any("[DisabledFunction][Exit]" in msg for msg in log_messages), "Exit should not be logged when disabled"
# Coherence:OK should still be logged (internal tracking)
assert any("[DisabledFunction][COHERENCE:OK]" in msg for msg in log_messages), "Coherence should still be logged"
# "Entering DisabledFunction" (explicit logger.reason()) should NOT be logged when disabled
assert not any("Entering" in msg for msg in log_messages), "REASON entry should not be logged when disabled"
# REFLECT should still be logged (internal tracking, not gated by _enable_belief_state)
assert any("[REFLECT]" in msg for msg in log_messages), "REFLECT should still be logged"
# [/DEF:test_enable_belief_state_flag:Function]

View File

@@ -110,7 +110,7 @@ class IdMappingService:
"""
with belief_scope("IdMappingService.sync_environment"):
logger.info(
f"[IdMappingService.sync_environment][Action] Starting sync for environment {environment_id} (incremental={incremental})"
f"[IdMappingService.sync_environment][REASON] Starting sync for environment {environment_id} (incremental={incremental})"
)
# Implementation Note: In a real scenario, superset_client needs to be an instance
@@ -224,7 +224,7 @@ class IdMappingService:
if deleted:
total_deleted += deleted
logger.info(
f"[IdMappingService.sync_environment][Action] Removed {deleted} stale {endpoint} mapping(s) for {environment_id}"
f"[IdMappingService.sync_environment][REASON] Removed {deleted} stale {endpoint} mapping(s) for {environment_id}"
)
except Exception as loop_e:

View File

@@ -299,7 +299,7 @@ class SupersetClientBase:
pagination_options={"base_query": validated, "results_field": "result"},
)
app_logger.info(
"[get_all_resources][Exit] Fetched %d %s resources.",
"[get_all_resources][REFLECT] Fetched %d %s resources.",
len(data),
resource_type,
)

View File

@@ -292,7 +292,7 @@ class SupersetDashboardsCrudMixin:
self._validate_export_response(response, dashboard_id)
filename = self._resolve_export_filename(response, dashboard_id)
app_logger.info(
"[export_dashboard][Exit] Exported dashboard %s to %s.",
"[export_dashboard][REFLECT] Exported dashboard %s to %s.",
dashboard_id, filename,
)
return response.content, filename

View File

@@ -39,7 +39,7 @@ class SupersetDashboardsListMixin:
},
)
total_count = len(paginated_data)
app_logger.info("[get_dashboards][Exit] Found %d dashboards.", total_count)
app_logger.info("[get_dashboards][REFLECT] Found %d dashboards.", total_count)
return total_count, paginated_data
# [/DEF:SupersetClientGetDashboards:Function]

View File

@@ -33,7 +33,7 @@ class SupersetDatabasesMixin:
},
)
total_count = len(paginated_data)
app_logger.info("[get_databases][Exit] Found %d databases.", total_count)
app_logger.info("[get_databases][REFLECT] Found %d databases.", total_count)
return total_count, paginated_data
# [/DEF:SupersetClientGetDatabases:Function]
@@ -49,7 +49,7 @@ class SupersetDatabasesMixin:
method="GET", endpoint=f"/database/{database_id}"
)
response = cast(Dict, response)
app_logger.info("[get_database][Exit] Got database %s.", database_id)
app_logger.info("[get_database][REFLECT] Got database %s.", database_id)
return response
# [/DEF:SupersetClientGetDatabase:Function]

View File

@@ -32,7 +32,7 @@ class SupersetDatasetsMixin:
},
)
total_count = len(paginated_data)
app_logger.info("[get_datasets][Exit] Found %d datasets.", total_count)
app_logger.info("[get_datasets][REFLECT] Found %d datasets.", total_count)
return total_count, paginated_data
# [/DEF:SupersetClientGetDatasets:Function]
@@ -169,7 +169,7 @@ class SupersetDatasetsMixin:
}
app_logger.info(
f"[get_dataset_detail][Exit] Got dataset {dataset_id} with {len(column_info)} columns and {len(linked_dashboards)} linked dashboards"
f"[get_dataset_detail][REFLECT] Got dataset {dataset_id} with {len(column_info)} columns and {len(linked_dashboards)} linked dashboards"
)
return result
@@ -186,7 +186,7 @@ class SupersetDatasetsMixin:
method="GET", endpoint=f"/dataset/{dataset_id}"
)
response = cast(Dict, response)
app_logger.info("[get_dataset][Exit] Got dataset %s.", dataset_id)
app_logger.info("[get_dataset][REFLECT] Got dataset %s.", dataset_id)
return response
# [/DEF:SupersetClientGetDataset:Function]
@@ -206,7 +206,7 @@ class SupersetDatasetsMixin:
headers={"Content-Type": "application/json"},
)
response = cast(Dict, response)
app_logger.info("[update_dataset][Exit] Updated dataset %s.", dataset_id)
app_logger.info("[update_dataset][REFLECT] Updated dataset %s.", dataset_id)
return response
# [/DEF:SupersetClientUpdateDataset:Function]

View File

@@ -149,7 +149,7 @@ class AsyncAPIClient:
}
self._authenticated = True
SupersetAuthCache.set(self._auth_cache_key, self._tokens)
app_logger.info("[async_authenticate][Exit] Authenticated successfully.")
app_logger.info("[async_authenticate][REFLECT] Authenticated successfully.")
return self._tokens
except httpx.HTTPStatusError as exc:
SupersetAuthCache.invalidate(self._auth_cache_key)

View File

@@ -81,7 +81,7 @@ def remove_empty_directories(root_dir: str) -> int:
app_logger.info("[remove_empty_directories][State] Removed empty directory: %s", current_dir)
except OSError as e:
app_logger.error("[remove_empty_directories][Failure] Failed to remove %s: %s", current_dir, e)
app_logger.info("[remove_empty_directories][Exit] Removed %d empty directories.", removed_count)
app_logger.info("[remove_empty_directories][REFLECT] Removed %d empty directories.", removed_count)
return removed_count
# #endregion remove_empty_directories
@@ -354,7 +354,7 @@ def create_dashboard_export(zip_path: Union[str, Path], source_paths: List[Union
if item.is_file() and item.suffix.lower() not in exclude_ext:
arcname = item.relative_to(src_path.parent)
zipf.write(item, arcname)
app_logger.info("[create_dashboard_export][Exit] Archive created: %s", zip_path)
app_logger.info("[create_dashboard_export][REFLECT] Archive created: %s", zip_path)
return True
except (IOError, zipfile.BadZipFile, AssertionError) as e:
app_logger.error("[create_dashboard_export][Failure] Error: %s", e, exc_info=True)

View File

@@ -162,7 +162,7 @@ class APIClient:
# @POST: APIClient instance is initialized with a session.
def __init__(self, config: Dict[str, Any], verify_ssl: bool = True, timeout: int = DEFAULT_TIMEOUT):
with belief_scope("__init__"):
app_logger.info("[APIClient.__init__][Entry] Initializing APIClient.")
app_logger.info("[APIClient.__init__][REASON] Initializing APIClient.")
self.base_url: str = self._normalize_base_url(config.get("base_url", ""))
self.api_base_url: str = f"{self.base_url}/api/v1"
self.auth = config.get("auth")
@@ -175,7 +175,7 @@ class APIClient:
verify_ssl,
)
self._authenticated = False
app_logger.info("[APIClient.__init__][Exit] APIClient initialized.")
app_logger.info("[APIClient.__init__][REFLECT] APIClient initialized.")
# [/DEF:APIClient.__init__:Function]
# [DEF:_init_session:Function]
@@ -291,7 +291,7 @@ class APIClient:
self._tokens = {"access_token": access_token, "csrf_token": csrf_response.json()["result"]}
self._authenticated = True
SupersetAuthCache.set(self._auth_cache_key, self._tokens)
app_logger.info("[authenticate][Exit] Authenticated successfully.")
app_logger.info("[authenticate][REFLECT] Authenticated successfully.")
return self._tokens
except requests.exceptions.HTTPError as e:
SupersetAuthCache.invalidate(self._auth_cache_key)

View File

@@ -134,7 +134,7 @@ class GitPlugin(PluginBase):
# @POST: Плагин готов к выполнению задач.
async def initialize(self):
with belief_scope("GitPlugin.initialize"):
app_logger.info("[GitPlugin.initialize][Action] Initializing Git Integration Plugin logic.")
app_logger.info("[GitPlugin.initialize][REASON] Initializing Git Integration Plugin logic.")
# [DEF:execute:Function]
# @PURPOSE: Основной метод выполнения задач плагина с поддержкой TaskContext.
@@ -245,9 +245,9 @@ class GitPlugin(PluginBase):
# 5. Автоматический staging изменений (не коммит, чтобы юзер мог проверить diff)
try:
repo.git.add(A=True)
app_logger.info("[_handle_sync][Action] Changes staged in git")
app_logger.info("[_handle_sync][REASON] Changes staged in git")
except Exception as ge:
app_logger.warning(f"[_handle_sync][Action] Failed to stage changes: {ge}")
app_logger.warning(f"[_handle_sync][REASON] Failed to stage changes: {ge}")
app_logger.info(f"[_handle_sync][Coherence:OK] Dashboard {dashboard_id} synced successfully.")
return {"status": "success", "message": "Dashboard synced and flattened in local repository"}
@@ -315,7 +315,7 @@ class GitPlugin(PluginBase):
f.write(zip_buffer.getvalue())
try:
app_logger.info(f"[_handle_deploy][Action] Importing dashboard to {env.name}")
app_logger.info(f"[_handle_deploy][REASON] Importing dashboard to {env.name}")
result = client.import_dashboard(temp_zip_path)
app_logger.info(f"[_handle_deploy][Coherence:OK] Deployment successful for dashboard {dashboard_id}.")
return {"status": "success", "message": f"Dashboard deployed to {env.name}", "details": result}
@@ -336,13 +336,13 @@ class GitPlugin(PluginBase):
# @RETURN: Environment - Объект конфигурации окружения.
def _get_env(self, env_id: Optional[str] = None):
with belief_scope("GitPlugin._get_env"):
app_logger.info(f"[_get_env][Entry] Fetching environment for ID: {env_id}")
app_logger.info(f"[_get_env][REASON] Fetching environment for ID: {env_id}")
# Priority 1: ConfigManager (config.json)
if env_id:
env = self.config_manager.get_environment(env_id)
if env:
app_logger.info(f"[_get_env][Exit] Found environment by ID in ConfigManager: {env.name}")
app_logger.info(f"[_get_env][REFLECT] Found environment by ID in ConfigManager: {env.name}")
return env
# Priority 2: Database (DeploymentEnvironment)
@@ -360,7 +360,7 @@ class GitPlugin(PluginBase):
db_env = db.query(DeploymentEnvironment).first()
if db_env:
app_logger.info(f"[_get_env][Exit] Found environment in DB: {db_env.name}")
app_logger.info(f"[_get_env][REFLECT] Found environment in DB: {db_env.name}")
from src.core.config_models import Environment
# Use token as password for SupersetClient
return Environment(
@@ -382,11 +382,11 @@ class GitPlugin(PluginBase):
# but we have other envs, maybe it's one of them?
env = next((e for e in envs if e.id == env_id), None)
if env:
app_logger.info(f"[_get_env][Exit] Found environment {env_id} in ConfigManager list")
app_logger.info(f"[_get_env][REFLECT] Found environment {env_id} in ConfigManager list")
return env
if not env_id:
app_logger.info(f"[_get_env][Exit] Using first environment from ConfigManager: {envs[0].name}")
app_logger.info(f"[_get_env][REFLECT] Using first environment from ConfigManager: {envs[0].name}")
return envs[0]
app_logger.error(f"[_get_env][Coherence:Failed] No environments configured (searched config.json and DB). env_id={env_id}")

View File

@@ -186,7 +186,7 @@ class StoragePlugin(PluginBase):
# Use singular name for consistency with BackupPlugin and GitService
path = root / category.value
path.mkdir(parents=True, exist_ok=True)
logger.debug(f"[StoragePlugin][Action] Ensured directory: {path}")
logger.debug(f"[StoragePlugin][REASON] Ensured directory: {path}")
# [/DEF:ensure_directories:Function]
# [DEF:validate_path:Function]
@@ -222,7 +222,7 @@ class StoragePlugin(PluginBase):
with belief_scope("StoragePlugin:list_files"):
root = self.get_storage_root()
logger.info(
f"[StoragePlugin][Action] Listing files in root: {root}, category: {category}, subpath: {subpath}, recursive: {recursive}"
f"[StoragePlugin][REASON] Listing files in root: {root}, category: {category}, subpath: {subpath}, recursive: {recursive}"
)
files = []
@@ -258,7 +258,7 @@ class StoragePlugin(PluginBase):
if not target_dir.exists():
continue
logger.debug(f"[StoragePlugin][Action] Scanning directory: {target_dir}")
logger.debug(f"[StoragePlugin][REASON] Scanning directory: {target_dir}")
if recursive:
for current_root, dirs, filenames in os.walk(target_dir):
@@ -358,7 +358,7 @@ class StoragePlugin(PluginBase):
shutil.rmtree(full_path)
else:
full_path.unlink()
logger.info(f"[StoragePlugin][Action] Deleted: {full_path}")
logger.info(f"[StoragePlugin][REASON] Deleted: {full_path}")
else:
raise FileNotFoundError(f"Item {path} not found")
# [/DEF:delete_file:Function]

View File

@@ -165,7 +165,7 @@ def _migrate_config(engine, legacy_config_path: Optional[Path]) -> int:
with belief_scope("_migrate_config"):
if legacy_config_path is None:
logger.info(
"[_migrate_config][Action] No legacy config.json found, skipping"
"[_migrate_config][REASON] No legacy config.json found, skipping"
)
return 0
@@ -328,7 +328,7 @@ def run_migration(
) -> Dict[str, int]:
with belief_scope("run_migration"):
logger.info(
"[run_migration][Entry] sqlite=%s target=%s", sqlite_path, target_url
"[run_migration][REASON] sqlite=%s target=%s", sqlite_path, target_url
)
if not sqlite_path.exists():
raise FileNotFoundError(f"SQLite source not found: {sqlite_path}")

View File

@@ -382,7 +382,7 @@ def main() -> None:
args = _parse_args()
result = seed_superset_load_data(args)
logger.info(
f"[COHERENCE:OK] Result summary: {json.dumps(result, ensure_ascii=True)}"
f"[REFLECT] Result summary: {json.dumps(result, ensure_ascii=True)}"
)

View File

@@ -133,7 +133,7 @@ class GitServiceBase:
if source_abs == target_abs:
return source_abs
if os.path.exists(target_abs):
logger.warning(f"[_migrate_repo_directory][Action] Target already exists, keeping source path: {target_abs}")
logger.warning(f"[_migrate_repo_directory][REASON] Target already exists, keeping source path: {target_abs}")
return source_abs
Path(target_abs).parent.mkdir(parents=True, exist_ok=True)
try:
@@ -210,11 +210,11 @@ class GitServiceBase:
else:
auth_url = remote_url
if os.path.exists(repo_path):
logger.info(f"[init_repo][Action] Opening existing repo at {repo_path}")
logger.info(f"[init_repo][REASON] Opening existing repo at {repo_path}")
try:
repo = Repo(repo_path)
except (InvalidGitRepositoryError, NoSuchPathError):
logger.warning(f"[init_repo][Action] Existing path is not a Git repository, recreating: {repo_path}")
logger.warning(f"[init_repo][REASON] Existing path is not a Git repository, recreating: {repo_path}")
stale_path = Path(repo_path)
if stale_path.exists():
shutil.rmtree(stale_path, ignore_errors=True)
@@ -226,7 +226,7 @@ class GitServiceBase:
repo = Repo.clone_from(auth_url, repo_path)
self._ensure_gitflow_branches(repo, dashboard_id)
return repo
logger.info(f"[init_repo][Action] Cloning {remote_url} to {repo_path}")
logger.info(f"[init_repo][REASON] Cloning {remote_url} to {repo_path}")
repo = Repo.clone_from(auth_url, repo_path)
self._ensure_gitflow_branches(repo, dashboard_id)
return repo
@@ -307,7 +307,7 @@ class GitServiceBase:
with repo.config_writer(config_level="repository") as config_writer:
config_writer.set_value("user", "name", normalized_username)
config_writer.set_value("user", "email", normalized_email)
logger.info("[configure_identity][Action] Applied repository-local git identity for dashboard %s", dashboard_id)
logger.info("[configure_identity][REASON] Applied repository-local git identity for dashboard %s", dashboard_id)
except Exception as e:
logger.error(f"[configure_identity][Coherence:Failed] Failed to configure git identity: {e}")
raise HTTPException(status_code=500, detail=f"Failed to configure git identity: {str(e)}")

View File

@@ -32,24 +32,24 @@ class GitServiceBranchMixin:
base_commit = local_heads["main"].commit
if base_commit is None:
logger.warning(
f"[_ensure_gitflow_branches][Action] Skipping branch bootstrap for dashboard {dashboard_id}: repository has no commits"
f"[_ensure_gitflow_branches][REASON] Skipping branch bootstrap for dashboard {dashboard_id}: repository has no commits"
)
return
if "main" not in local_heads:
local_heads["main"] = repo.create_head("main", base_commit)
logger.info(f"[_ensure_gitflow_branches][Action] Created local branch main for dashboard {dashboard_id}")
logger.info(f"[_ensure_gitflow_branches][REASON] Created local branch main for dashboard {dashboard_id}")
for branch_name in ("dev", "preprod"):
if branch_name in local_heads:
continue
local_heads[branch_name] = repo.create_head(branch_name, local_heads["main"].commit)
logger.info(
f"[_ensure_gitflow_branches][Action] Created local branch {branch_name} for dashboard {dashboard_id}"
f"[_ensure_gitflow_branches][REASON] Created local branch {branch_name} for dashboard {dashboard_id}"
)
try:
origin = repo.remote(name="origin")
except ValueError:
logger.info(
f"[_ensure_gitflow_branches][Action] Remote origin is not configured for dashboard {dashboard_id}; skipping remote branch creation"
f"[_ensure_gitflow_branches][REASON] Remote origin is not configured for dashboard {dashboard_id}; skipping remote branch creation"
)
return
remote_branch_names = set()
@@ -60,14 +60,14 @@ class GitServiceBranchMixin:
if remote_head:
remote_branch_names.add(str(remote_head))
except Exception as e:
logger.warning(f"[_ensure_gitflow_branches][Action] Failed to fetch origin refs: {e}")
logger.warning(f"[_ensure_gitflow_branches][REASON] Failed to fetch origin refs: {e}")
for branch_name in required_branches:
if branch_name in remote_branch_names:
continue
try:
origin.push(refspec=f"{branch_name}:{branch_name}")
logger.info(
f"[_ensure_gitflow_branches][Action] Pushed branch {branch_name} to origin for dashboard {dashboard_id}"
f"[_ensure_gitflow_branches][REASON] Pushed branch {branch_name} to origin for dashboard {dashboard_id}"
)
except Exception as e:
logger.error(f"[_ensure_gitflow_branches][Coherence:Failed] Failed to push branch {branch_name} to origin: {e}")
@@ -77,9 +77,9 @@ class GitServiceBranchMixin:
)
try:
repo.git.checkout("dev")
logger.info(f"[_ensure_gitflow_branches][Action] Checked out default branch dev for dashboard {dashboard_id}")
logger.info(f"[_ensure_gitflow_branches][REASON] Checked out default branch dev for dashboard {dashboard_id}")
except Exception as e:
logger.warning(f"[_ensure_gitflow_branches][Action] Could not checkout dev branch for dashboard {dashboard_id}: {e}")
logger.warning(f"[_ensure_gitflow_branches][REASON] Could not checkout dev branch for dashboard {dashboard_id}: {e}")
# [/DEF:_ensure_gitflow_branches:Function]
# [DEF:list_branches:Function]
@@ -90,7 +90,7 @@ class GitServiceBranchMixin:
def list_branches(self, dashboard_id: int) -> List[dict]:
with belief_scope("GitService.list_branches"):
repo = self.get_repo(dashboard_id)
logger.info(f"[list_branches][Action] Listing branches for {dashboard_id}. Refs: {repo.refs}")
logger.info(f"[list_branches][REASON] Listing branches for {dashboard_id}. Refs: {repo.refs}")
branches = []
for ref in repo.refs:
try:
@@ -104,7 +104,7 @@ class GitServiceBranchMixin:
"last_updated": datetime.fromtimestamp(ref.commit.committed_date) if hasattr(ref, 'commit') else datetime.utcnow()
})
except Exception as e:
logger.warning(f"[list_branches][Action] Skipping ref {ref}: {e}")
logger.warning(f"[list_branches][REASON] Skipping ref {ref}: {e}")
try:
active_name = repo.active_branch.name
if not any(b['name'] == active_name for b in branches):
@@ -113,7 +113,7 @@ class GitServiceBranchMixin:
"is_remote": False, "last_updated": datetime.utcnow()
})
except Exception as e:
logger.warning(f"[list_branches][Action] Could not determine active branch: {e}")
logger.warning(f"[list_branches][REASON] Could not determine active branch: {e}")
if not branches:
branches.append({
"name": "dev", "commit_hash": "0000000",
@@ -131,9 +131,9 @@ class GitServiceBranchMixin:
def create_branch(self, dashboard_id: int, name: str, from_branch: str = "main"):
with belief_scope("GitService.create_branch"):
repo = self.get_repo(dashboard_id)
logger.info(f"[create_branch][Action] Creating branch {name} from {from_branch}")
logger.info(f"[create_branch][REASON] Creating branch {name} from {from_branch}")
if not repo.heads and not repo.remotes:
logger.warning("[create_branch][Action] Repository is empty. Creating initial commit to enable branching.")
logger.warning("[create_branch][REASON] Repository is empty. Creating initial commit to enable branching.")
readme_path = os.path.join(repo.working_dir, "README.md")
if not os.path.exists(readme_path):
with open(readme_path, "w") as f:
@@ -143,7 +143,7 @@ class GitServiceBranchMixin:
try:
repo.commit(from_branch)
except Exception:
logger.warning(f"[create_branch][Action] Source branch {from_branch} not found, using HEAD")
logger.warning(f"[create_branch][REASON] Source branch {from_branch} not found, using HEAD")
from_branch = repo.head
try:
new_branch = repo.create_head(name, from_branch)
@@ -160,7 +160,7 @@ class GitServiceBranchMixin:
def checkout_branch(self, dashboard_id: int, name: str):
with belief_scope("GitService.checkout_branch"):
repo = self.get_repo(dashboard_id)
logger.info(f"[checkout_branch][Action] Checking out branch {name}")
logger.info(f"[checkout_branch][REASON] Checking out branch {name}")
repo.git.checkout(name)
# [/DEF:checkout_branch:Function]
@@ -174,13 +174,13 @@ class GitServiceBranchMixin:
with belief_scope("GitService.commit_changes"):
repo = self.get_repo(dashboard_id)
if not repo.is_dirty(untracked_files=True) and not files:
logger.info(f"[commit_changes][Action] No changes to commit for dashboard {dashboard_id}")
logger.info(f"[commit_changes][REASON] No changes to commit for dashboard {dashboard_id}")
return
if files:
logger.info(f"[commit_changes][Action] Staging files: {files}")
logger.info(f"[commit_changes][REASON] Staging files: {files}")
repo.index.add(files)
else:
logger.info("[commit_changes][Action] Staging all changes")
logger.info("[commit_changes][REASON] Staging all changes")
repo.git.add(A=True)
repo.index.commit(message)
logger.info(f"[commit_changes][Coherence:OK] Committed changes with message: {message}")

View File

@@ -23,7 +23,7 @@ class GitServiceGiteaMixin:
async def test_connection(self, provider: GitProvider, url: str, pat: str) -> bool:
with belief_scope("GitService.test_connection"):
if ".local" in url or "localhost" in url:
logger.info("[test_connection][Action] Local/Offline mode detected for URL")
logger.info("[test_connection][REASON] Local/Offline mode detected for URL")
return True
if not url.startswith(('http://', 'https://')):
logger.error(f"[test_connection][Coherence:Failed] Invalid URL protocol: {url}")
@@ -221,7 +221,7 @@ class GitServiceGiteaMixin:
)
if should_retry_with_fallback:
logger.warning(
"[create_gitea_pull_request][Action] Primary Gitea URL not found, retrying with remote host: %s",
"[create_gitea_pull_request][REASON] Primary Gitea URL not found, retrying with remote host: %s",
fallback_url,
)
active_server_url = fallback_url

View File

@@ -153,7 +153,7 @@ class GitServiceStatusMixin:
"files_changed": list(commit.stats.files.keys())
})
except Exception as e:
logger.warning(f"[get_commit_history][Action] Could not retrieve commit history for dashboard {dashboard_id}: {e}")
logger.warning(f"[get_commit_history][REASON] Could not retrieve commit history for dashboard {dashboard_id}: {e}")
return []
return commits
# [/DEF:get_commit_history:Function]

View File

@@ -61,7 +61,7 @@ class GitServiceSyncMixin:
session.close()
except Exception as diag_error:
logger.warning(
"[push_changes][Action] Failed to load repository binding diagnostics for dashboard %s: %s",
"[push_changes][REASON] Failed to load repository binding diagnostics for dashboard %s: %s",
dashboard_id, diag_error,
)
realigned_origin_url = self._align_origin_host_with_config(
@@ -76,12 +76,12 @@ class GitServiceSyncMixin:
except Exception:
origin_urls = []
logger.info(
"[push_changes][Action] Push diagnostics dashboard=%s config_id=%s config_url=%s binding_remote_url=%s origin_urls=%s origin_realigned=%s",
"[push_changes][REASON] Push diagnostics dashboard=%s config_id=%s config_url=%s binding_remote_url=%s origin_urls=%s origin_realigned=%s",
dashboard_id, binding_config_id, binding_config_url, binding_remote_url, origin_urls, bool(realigned_origin_url),
)
try:
current_branch = repo.active_branch
logger.info(f"[push_changes][Action] Pushing branch {current_branch.name} to origin")
logger.info(f"[push_changes][REASON] Pushing branch {current_branch.name} to origin")
tracking_branch = None
try:
tracking_branch = current_branch.tracking_branch()
@@ -121,7 +121,7 @@ class GitServiceSyncMixin:
if os.path.exists(merge_head_path):
payload = self._build_unfinished_merge_payload(repo)
logger.warning(
"[pull_changes][Action] Unfinished merge detected for dashboard %s (repo_path=%s git_dir=%s branch=%s merge_head=%s merge_msg=%s)",
"[pull_changes][REASON] Unfinished merge detected for dashboard %s (repo_path=%s git_dir=%s branch=%s merge_head=%s merge_msg=%s)",
dashboard_id, payload["repository_path"], payload["git_dir"],
payload["current_branch"], payload["merge_head"], payload["merge_message_preview"],
)
@@ -134,14 +134,14 @@ class GitServiceSyncMixin:
except Exception:
origin_urls = []
logger.info(
"[pull_changes][Action] Pull diagnostics dashboard=%s repo_path=%s branch=%s origin_urls=%s",
"[pull_changes][REASON] Pull diagnostics dashboard=%s repo_path=%s branch=%s origin_urls=%s",
dashboard_id, repo.working_tree_dir, current_branch, origin_urls,
)
origin.fetch(prune=True)
remote_ref = f"origin/{current_branch}"
has_remote_branch = any(ref.name == remote_ref for ref in repo.refs)
logger.info(
"[pull_changes][Action] Pull remote branch check dashboard=%s branch=%s remote_ref=%s exists=%s",
"[pull_changes][REASON] Pull remote branch check dashboard=%s branch=%s remote_ref=%s exists=%s",
dashboard_id, current_branch, remote_ref, has_remote_branch,
)
if not has_remote_branch:
@@ -149,7 +149,7 @@ class GitServiceSyncMixin:
status_code=409,
detail=f"Remote branch '{current_branch}' does not exist yet. Push this branch first.",
)
logger.info(f"[pull_changes][Action] Pulling changes from origin/{current_branch}")
logger.info(f"[pull_changes][REASON] Pulling changes from origin/{current_branch}")
repo.git.pull("--no-rebase", "origin", current_branch)
except ValueError:
logger.error(f"[pull_changes][Coherence:Failed] Remote 'origin' not found for dashboard {dashboard_id}")

View File

@@ -116,7 +116,7 @@ class GitServiceUrlMixin:
if not aligned_url:
return None
logger.warning(
"[_align_origin_host_with_config][Action] Host mismatch for dashboard %s: config_host=%s origin_host=%s, applying origin.set_url",
"[_align_origin_host_with_config][REASON] Host mismatch for dashboard %s: config_host=%s origin_host=%s, applying origin.set_url",
dashboard_id, config_host, origin_host,
)
try:
@@ -142,7 +142,7 @@ class GitServiceUrlMixin:
session.close()
except Exception as e:
logger.warning(
"[_align_origin_host_with_config][Action] Failed to persist aligned remote_url for dashboard %s: %s",
"[_align_origin_host_with_config][REASON] Failed to persist aligned remote_url for dashboard %s: %s",
dashboard_id, e,
)
return aligned_url

View File

@@ -28,7 +28,7 @@ class ResourceService:
def __init__(self):
with belief_scope("ResourceService.__init__"):
self.git_service = GitService()
logger.info("[ResourceService][Action] Initialized ResourceService")
logger.info("[ResourceService][REASON] Initialized ResourceService")
# [/DEF:ResourceService_init:Function]
# [DEF:get_dashboards_with_status:Function]