From 1f84be28a5d059f830e807f41e57a9082f7aea52 Mon Sep 17 00:00:00 2001 From: abhizipstack Date: Wed, 15 Apr 2026 11:57:22 +0530 Subject: [PATCH] fix: reduce logs-panel noise and make messages readable (OR-1457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layer 1 — silence the worst offender - Demote UsingCachedObject from InfoLevel to DebugLevel so the per-query "Using Cached Object of bigquery_connection_object" spam no longer reaches the UI at default verbosity. Layer 2A — fix data bugs leaking dev internals into the UI - ProcessingModel: avoid Processing Model : "" by using cls.__name__ with file_name as a fallback, instead of str(cls) which can be empty for dynamically generated no-code model classes. - ExecStatus / Materialization: stop str(Enum) from leaking the dotted enum names (ExecStatus.Success, Materialization.EPHEMERAL) into user messages; use .value so the UI shows SUCCESS / OK / TABLE. - Summary counts: parse_and_fire_reports compared end_status against ExecStatus.Success/Error but end_status is set to OK/Fail, so pass/error counters stayed zero. Compare against the correct end-status values so DONE PASS=N now reflects reality. Frontend - Socket handler now captures the level alongside the message; each log entry is stored as { level, message } instead of a raw string. - New log-level selector in the bottom logs tab: All logs / Info & above / Warnings & errors / Errors only Default is "Info & above" (hides debug noise out of the box). Choice persists in localStorage under visitran.logsLevel. - Log rows are tinted by severity (grey/default/amber/red) for quick scanning when All is selected. Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/visitran/events/printer.py | 8 +- backend/visitran/events/types.py | 2 +- backend/visitran/visitran.py | 32 ++++---- .../editor/no-code-model/no-code-model.jsx | 78 ++++++++++++++----- 4 files changed, 81 insertions(+), 39 deletions(-) diff --git a/backend/visitran/events/printer.py b/backend/visitran/events/printer.py index bee84e5..19f1a19 100644 --- a/backend/visitran/events/printer.py +++ b/backend/visitran/events/printer.py @@ -86,13 +86,13 @@ def parse_and_fire_reports() -> None: status=iterate_result.status, ) ) - if iterate_result.end_status == str(ExecStatus.Success): + if iterate_result.end_status == ExecStatus.OK.value: pass_count += 1 - if iterate_result.end_status == str(ExecStatus.Warn): + elif iterate_result.end_status == ExecStatus.Warn.value: warn_count += 1 - if iterate_result.end_status == str(ExecStatus.Error): + elif iterate_result.end_status == ExecStatus.Fail.value: error_count += 1 - if iterate_result.end_status == str(ExecStatus.Skipped): + elif iterate_result.end_status == ExecStatus.Skipped.value: skip_count += 1 functions.fire_event( diff --git a/backend/visitran/events/types.py b/backend/visitran/events/types.py index f69c25c..104dd9a 100644 --- a/backend/visitran/events/types.py +++ b/backend/visitran/events/types.py @@ -469,7 +469,7 @@ def message(self) -> str: @dataclass -class UsingCachedObject(InfoLevel, proto_type.UsingCachedObject): +class UsingCachedObject(DebugLevel, proto_type.UsingCachedObject): def code(self) -> str: return "Z009" diff --git a/backend/visitran/visitran.py b/backend/visitran/visitran.py index c75b20e..8e8044e 100644 --- a/backend/visitran/visitran.py +++ b/backend/visitran/visitran.py @@ -260,7 +260,7 @@ def execute_graph(self) -> None: destination_table_obj=( str(node.destination_table_obj) if hasattr(node, "destination_table_obj") else "" ), - materialization=str(node.materialization), + materialization=node.materialization.value if hasattr(node.materialization, "value") else str(node.materialization), select_statement=(str(node.select_statement) if hasattr(node, "select_statement") else ""), source_schema_name=node.source_schema_name, source_table_name=node.source_table_name, @@ -276,8 +276,8 @@ def execute_graph(self) -> None: ending_time=datetime.datetime.now(), failures=False, info_message=f"Running {node_name}", - status=str(ExecStatus.Success), - end_status=str(ExecStatus.OK), + status=ExecStatus.Success.value, + end_status=ExecStatus.OK.value, ) sequence_number += 1 BASE_RESULT.append(base_result) @@ -291,8 +291,8 @@ def execute_graph(self) -> None: node_name=str(node_name), sequence_num=sequence_number, ending_time=datetime.datetime.now(), - status=str(ExecStatus.Error), - end_status=str(ExecStatus.Fail), + status=ExecStatus.Error.value, + end_status=ExecStatus.Fail.value, info_message=f"Error occurred while running {node_name}", failures=True, ) @@ -438,7 +438,7 @@ def search_n_run_models(self, model_name: str = None, model_names: list = None) ) for cls in cls_set: - fire_event(ProcessingModel(cls=str(cls))) + fire_event(ProcessingModel(cls=getattr(cls, "__name__", "") or file_name)) # process each model only once # they might be imported in several places! @@ -550,9 +550,9 @@ def search_n_run_tests(self) -> None: sequence_num=test_files.index(tf), failures=True, ending_time=datetime.datetime.now(), - status=str(ExecStatus.Error), + status=ExecStatus.Error.value, info_message=f"Error occured in {tf} execution", - end_status=str(ExecStatus.Fail), + end_status=ExecStatus.Fail.value, ) BASE_RESULT.append(base_result) parse_and_fire_reports() @@ -611,8 +611,8 @@ def _run_tests(self, tf: str, tst_cls: Any, tst_obj: Any, test_methods: list[str info_message=f"Test assertion error: \ {repr(err)} in {test_func.__name__}", ending_time=datetime.datetime.now(), - status=str(ExecStatus.Error), - end_status=str(ExecStatus.Fail), + status=ExecStatus.Error.value, + end_status=ExecStatus.Fail.value, sequence_num=sequence_num, ) BASE_RESULT.append(base_result) @@ -624,8 +624,8 @@ def _run_tests(self, tf: str, tst_cls: Any, tst_obj: Any, test_methods: list[str ending_time=datetime.datetime.now(), failures=False, info_message=f"Running {tf}", - status=str(ExecStatus.Success), - end_status=str(ExecStatus.OK), + status=ExecStatus.Success.value, + end_status=ExecStatus.OK.value, sequence_num=sequence_num, ) BASE_RESULT.append(base_result) @@ -727,14 +727,14 @@ def validate_and_run_seed(self, seed_file, session_id: str) -> dict[str, str]: seed_result = SeedResult( schema_name=schema, seed_path=file_name, - status=str(ExecStatus.START), + status=ExecStatus.START.value, ) SEED_RESULT.append(seed_result) seed_obj: BaseSeed = self.db_adapter.run_seeds(schema=schema, abs_path=file_path) seed_result = SeedResult( schema_name=schema, seed_path=file_name, - status=str(ExecStatus.COMPLETED), + status=ExecStatus.COMPLETED.value, ) SEED_RESULT.append(seed_result) parse_and_fire_seed_report() @@ -789,14 +789,14 @@ def run_snapshot(self) -> None: snapshot_result = SnapshotResult( source_table=obj.source_table_name, unique_key=obj.unique_key, - status=str(ExecStatus.START), + status=ExecStatus.START.value, ) SNAPSHOT_RESULT.append(snapshot_result) self.db_adapter.run_scd(visitran_snapshot=obj) snapshot_result = SnapshotResult( source_table=obj.source_table_name, unique_key=obj.unique_key, - status=str(ExecStatus.COMPLETED), + status=ExecStatus.COMPLETED.value, ) SNAPSHOT_RESULT.append(snapshot_result) parse_and_fire_snapshot_report() diff --git a/frontend/src/ide/editor/no-code-model/no-code-model.jsx b/frontend/src/ide/editor/no-code-model/no-code-model.jsx index 80304d0..5c6f5d5 100644 --- a/frontend/src/ide/editor/no-code-model/no-code-model.jsx +++ b/frontend/src/ide/editor/no-code-model/no-code-model.jsx @@ -4,6 +4,7 @@ import { Input, Modal, Pagination, + Select, Space, Table, Tabs, @@ -206,7 +207,9 @@ function NoCodeModel({ nodeData }) { const [seqEdges, setSeqEdges, onSeqEdgesChange] = useEdgesState(); const [reactFlowInstance, setReactFlowInstance] = useState(null); const [logsInfo, setLogsInfo] = useState([]); - // const logsInfo = []; + const [logsLevel, setLogsLevel] = useState( + () => localStorage.getItem("visitran.logsLevel") || "info" + ); const [reveal, setReveal] = useState(false); const [seqOrder, setSeqOrder] = useState({}); const [specRevert, setSpecRevert] = useState(false); @@ -366,6 +369,23 @@ function NoCodeModel({ nodeData }) { ALLOWED_ATTR: ["style"], }); + const LOG_LEVEL_RANK = { debug: 0, info: 1, warn: 2, warning: 2, error: 3 }; + const LOG_LEVEL_COLOR = { + debug: "#8c8c8c", + info: undefined, + warn: "#d48806", + warning: "#d48806", + error: "#cf1322", + }; + const filteredLogs = logsInfo.filter( + (entry) => + (LOG_LEVEL_RANK[entry.level] ?? 1) >= (LOG_LEVEL_RANK[logsLevel] ?? 1) + ); + const handleLogsLevelChange = (value) => { + setLogsLevel(value); + localStorage.setItem("visitran.logsLevel", value); + }; + const hideGenAIAndTimeTravelTabs = true; const BOTTOM_TABS = [ { @@ -643,21 +663,43 @@ function NoCodeModel({ nodeData }) { ), key: "logs", children: ( -
- {logsInfo?.map((el, index) => { - return ( + <> +
+