Created Dashboard and report generation#169
Conversation
| try: | ||
| if path.exists(): | ||
| path.unlink() | ||
| except OSError: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
General approach: avoid completely empty except blocks. Either (1) explicitly justify ignoring the exception with a comment, or (2) handle it in some lightweight way, such as logging the error while still allowing execution to continue. We must preserve existing functional behaviour: _clear_runtime_state should still not raise on OSError.
Best fix here: keep swallowing the exception but log it at a low severity (e.g., logging.debug or logging.warning) so that operational issues can be diagnosed. Since we can add imports of standard libraries, we can use Python’s logging module. This preserves the “best effort” semantics while addressing the “does nothing” concern.
Concrete changes in deceptgold/src/deceptgold/commands/dashboard.py:
- Add
import loggingalongside the existing imports. - Replace the
except OSError: passblock in_clear_runtime_statewith anexcept OSError as exc:that callslogging.debug(orlogging.warning) to record the failure, including the path and the exception message, and then continues.
No new methods or complex definitions are needed beyond the import; we can rely on the root logger configuration that the application likely already has, or accept default behaviour.
| @@ -14,6 +14,7 @@ | ||
| from datetime import datetime | ||
| from pathlib import Path | ||
| import socketserver | ||
| import logging | ||
| from cyclopts import App | ||
| import qrcode_terminal | ||
|
|
||
| @@ -121,8 +122,9 @@ | ||
| try: | ||
| if path.exists(): | ||
| path.unlink() | ||
| except OSError: | ||
| pass | ||
| except OSError as exc: | ||
| # Best-effort cleanup: log and ignore failure to remove runtime files | ||
| logging.debug("Failed to remove runtime file %s: %s", path, exc) | ||
|
|
||
|
|
||
| def _resolve_display_host(host): |
| import ipaddress | ||
| if ipaddress.ip_address(candidate).is_private: | ||
| return candidate | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, to fix an empty except that only passes, either handle the exception meaningfully (logging, cleanup, fallback) or narrow the exception type and document why it is safe to ignore. The goal is to avoid completely hiding failures without explanation.
For _resolve_internal_bind_host, we should keep its current behavior—fall back to "127.0.0.1" on any error—but avoid silently swallowing the exception. The least intrusive fix is to add a debug/diagnostic message in the except block while still returning the same fallback. Since the function’s caller does not appear in the snippet, we should not change its return contract or add new exceptions. We also should not introduce new logging frameworks if unnecessary; a simple print to stderr or a comment can suffice.
Concretely, in deceptgold/src/deceptgold/commands/dashboard.py, modify the except Exception: block in _resolve_internal_bind_host (lines 147–148) to either:
- log a brief message indicating that resolving the internal bind host failed and that
"127.0.0.1"will be used, or - add a comment explicitly stating that the exception is intentionally ignored because we fall back to localhost.
To maintain functionality but improve diagnostics and satisfy CodeQL, we can replace pass with a print to sys.stderr using the already-imported sys. No new imports are required.
| @@ -144,8 +144,8 @@ | ||
| import ipaddress | ||
| if ipaddress.ip_address(candidate).is_private: | ||
| return candidate | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
| print(f"Could not resolve internal bind host, falling back to 127.0.0.1: {e}", file=sys.stderr) | ||
| return "127.0.0.1" | ||
|
|
||
|
|
|
|
||
| try: | ||
| os.kill(pid, signal.SIGTERM) | ||
| except OSError: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, empty except blocks should either (a) handle the exception in some meaningful way (logging, cleanup, recovery) or (b) explicitly document why it is safe to ignore the exception, often by narrowing the exception type and/or conditionally re-raising.
For this specific case, the best minimal fix is:
- Catch
OSErrorinto a variable. - Print a clear message indicating that stopping the dashboard failed, including the error message.
- Optionally, avoid printing "Dashboard stopped" when the
os.killcall fails, to keep user feedback accurate. - Still clear the runtime state file, because from the CLI’s perspective once
stophas been requested, we want to forget local state even if the OS-level kill failed; but we should be honest about that to the user.
Concretely, within deceptgold/src/deceptgold/commands/dashboard.py in the stop() function:
- Replace the
try/exceptwith atrythat sets astoppedflag on success and anexcept OSError as e:that reports the failure and keepsstoppedasFalse. - After the
try/except, call_clear_runtime_state()as before, but adjust the printed message depending on whether the kill was successful.
No new imports or helper functions are required.
| @@ -239,13 +239,18 @@ | ||
| print("Dashboard is not running") | ||
| return | ||
|
|
||
| stopped = False | ||
| try: | ||
| os.kill(pid, signal.SIGTERM) | ||
| except OSError: | ||
| pass | ||
| stopped = True | ||
| except OSError as e: | ||
| print(f"Failed to stop dashboard (pid {pid}): {e}") | ||
|
|
||
| _clear_runtime_state() | ||
| print("Dashboard stopped") | ||
| if stopped: | ||
| print("Dashboard stopped") | ||
| else: | ||
| print("Dashboard state cleared, but the process may still be running") | ||
|
|
||
|
|
||
| @dashboard_app.command(name="status", help="Show dashboard runtime status") |
| try: | ||
| with open(_trace_log_path, 'a', encoding='utf-8') as fh: | ||
| fh.writelines(lines) | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
To fix the problem, the except Exception: pass block should handle the error in a way that surfaces the issue without disrupting the main program. The general approaches are: (1) log the exception using an existing logging/notification mechanism, or (2) at least add a comment explicitly documenting why the exception is intentionally ignored. The best fix here is to log a brief message including the exception, while still swallowing it so that failures to write the trace log do not affect normal execution.
Concretely, in deceptgold/src/deceptgold/helper/opencanary/help_opencanary.py, within _wrap_log_with_forwarded_headers, replace:
72: try:
73: with open(_trace_log_path, 'a', encoding='utf-8') as fh:
74: fh.writelines(lines)
75: except Exception:
76: passwith code that catches the exception as exc and prints a short diagnostic to standard error. This avoids adding new external dependencies or touching other parts of the code. We can use the standard library sys.stderr for this, so we need to import sys at the top of the file alongside os and tracemalloc. No other methods or definitions are required.
| @@ -1,6 +1,7 @@ | ||
| import os | ||
| import tracemalloc | ||
| from functools import wraps | ||
| import sys | ||
|
|
||
| from deceptgold.configuration.config_manager import get_config | ||
| from deceptgold.helper.helper import parse_args | ||
| @@ -72,8 +73,13 @@ | ||
| try: | ||
| with open(_trace_log_path, 'a', encoding='utf-8') as fh: | ||
| fh.writelines(lines) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| # Best-effort logging: do not break request handling if trace logging fails, | ||
| # but emit a diagnostic to stderr to avoid silently swallowing errors. | ||
| print( | ||
| f"[DECEPTGOLD][MEM] Failed to write trace log to {_trace_log_path}: {exc}", | ||
| file=sys.stderr, | ||
| ) | ||
|
|
||
| return log_fn(logdata, *args, **kwargs) | ||
|
|
| # Get RSS (actual process memory) | ||
| try: | ||
| rss_before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
To fix the problem, the except Exception: blocks should stop being silent. They should either (a) log the exception in a lightweight way, or (b) include a clear explanatory comment stating why the exception is intentionally ignored. Since this code already writes to a log file (/tmp/deceptgold_memory_peak.log) and prints in global_twisted_error_handler, the best fix is to log these failures to the same log file used for memory diagnostics. This preserves the existing application behavior (no exceptions escape, metrics remain optional) while making failures visible to operators.
Concretely:
- At lines 110–113: wrap
resource.getrusageintryand, in theexcept, write a short message (including the exception string) to/tmp/deceptgold_memory_peak.log, but ignore any errors while writing so that the request handling is never affected. - At lines 134–137: do the same for the
rss_duringretrieval. - At lines 144–155: replace the empty
except Exception as e: passwith anexceptthat logs that writing the peak memory log failed.
We can implement this entirely within the shown function by adding small logging snippets to each except block, reusing the existing resource, tracemalloc, and path_str context. No new imports are strictly necessary; we can use the already-imported os if a timestamp is desired, but to minimize changes we can just log the exception and context string.
| @@ -109,8 +109,14 @@ | ||
| # Get RSS (actual process memory) | ||
| try: | ||
| rss_before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
| # Best-effort logging; ignore any failures here to avoid impacting request handling | ||
| try: | ||
| with open('/tmp/deceptgold_memory_peak.log', 'a', encoding='utf-8') as f: | ||
| f.write(f"\n[WARN] Failed to read initial RSS: {e}\n") | ||
| except Exception: | ||
| # Intentionally ignore logging failures | ||
| pass | ||
|
|
||
| if tracemalloc.is_tracing(): | ||
| mem_before, _ = tracemalloc.get_traced_memory() | ||
| @@ -133,8 +139,14 @@ | ||
| rss_during = 0 | ||
| try: | ||
| rss_during = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
| # Best-effort logging; ignore any failures here to avoid impacting request handling | ||
| try: | ||
| with open('/tmp/deceptgold_memory_peak.log', 'a', encoding='utf-8') as f: | ||
| f.write(f"\n[WARN] Failed to read RSS during request for {path_str!r}: {e}\n") | ||
| except Exception: | ||
| # Intentionally ignore logging failures | ||
| pass | ||
|
|
||
| if tracemalloc.is_tracing(): | ||
| mem_mid_end, peak_mid = tracemalloc.get_traced_memory() | ||
| @@ -152,7 +164,13 @@ | ||
| for stat in top_stats: | ||
| f.write(f" {stat.count} blocks | {stat.size/1024/1024:.2f} MB | {stat.traceback}\n") | ||
| except Exception as e: | ||
| pass | ||
| # Logging failures should not affect request handling; just record the error if possible | ||
| try: | ||
| with open('/tmp/deceptgold_memory_peak.log', 'a', encoding='utf-8') as f_fallback: | ||
| f_fallback.write(f"\n[WARN] Failed to write peak memory log for {path_str!r}: {e}\n") | ||
| except Exception: | ||
| # Intentionally ignore logging failures | ||
| pass | ||
|
|
||
| return result | ||
| finally: |
| f.write(f"Top Python allocations:\n") | ||
| for stat in top_stats: | ||
| f.write(f" {stat.count} blocks | {stat.size/1024/1024:.2f} MB | {stat.traceback}\n") | ||
| except Exception as e: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, empty except blocks should either (1) be removed so exceptions propagate, or (2) explicitly handle/log the exception and, if appropriate, re-raise. If an exception truly can be ignored, there should be a clear comment explaining why.
Here, the best fix that preserves existing functionality is to keep the exception from propagating (so request handling is not broken) but log it somewhere already used in this module. There is a global_twisted_error_handler at the top that currently prints unexpected errors; to avoid changing its interface or importing new logging frameworks, we can simply print a concise message to stderr when the debug log write fails, preserving the "best-effort" nature while no longer silently swallowing the error. We already import os and tracemalloc; printing does not require new imports.
Concretely, in deceptgold/src/deceptgold/helper/opencanary/help_opencanary.py, around line 154 we will replace:
154: except Exception as e:
155: passwith something like:
154: except Exception as e:
155: print(f"[!] Failed to write peak memory debug log for {path_str}: {e}")so the exception is visible. We will leave the later except Exception: at line 179 as-is, because the user report only targets line 154; we avoid speculative changes elsewhere.
No new imports, methods, or definitions are required.
| @@ -152,7 +152,7 @@ | ||
| for stat in top_stats: | ||
| f.write(f" {stat.count} blocks | {stat.size/1024/1024:.2f} MB | {stat.traceback}\n") | ||
| except Exception as e: | ||
| pass | ||
| print(f"[!] Failed to write peak memory debug log for {path_str}: {e}") | ||
|
|
||
| return result | ||
| finally: |
| rss_after = 0 | ||
| try: | ||
| rss_after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
General fix: instead of an empty except Exception: block, handle the exception in a way that preserves observability without changing control flow. For this context, that means catching the exception, logging a concise message to stderr (or using an existing logging mechanism if one were visible here), and possibly noting that RSS will be unavailable while still allowing the code to continue.
Best specific fix here: in the finally section where rss_after is updated (lines 165–169), replace the empty except Exception: block with an except Exception as exc: that writes a brief warning including the exception to sys.stderr. This does not alter any functional behavior of the application request handling, but ensures failures to read resource usage are at least visible. To keep changes minimal and not alter existing imports, we will import sys locally inside the except block rather than adding a new top-level import. We will also add a short explanatory comment to make the intent of ignoring the failure (beyond logging) explicit.
Concretely:
-
In
deceptgold/src/deceptgold/helper/opencanary/help_opencanary.py, locate thetry/exceptaroundresource.getrusagenear line 166. -
Replace:
166: try: 167: rss_after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 168: except Exception: 169: pass
with:
166: try: 167: rss_after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 168: except Exception as exc: 169: # Best-effort RSS collection; log failure but do not break request handling. 170: import sys 171: print(f"[deceptgold] Failed to collect rss_after via resource.getrusage: {exc}", file=sys.stderr)
-
Keep the rest of the logic unchanged.
| @@ -165,8 +165,10 @@ | ||
| rss_after = 0 | ||
| try: | ||
| rss_after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| # Best-effort RSS collection; log failure but do not break request handling. | ||
| import sys | ||
| print(f"[deceptgold] Failed to collect rss_after via resource.getrusage: {exc}", file=sys.stderr) | ||
|
|
||
| if tracemalloc.is_tracing() and mem_before is not None: | ||
| mem_after, peak = tracemalloc.get_traced_memory() |
| try: | ||
| with open('/tmp/deceptgold_memory_debug.log', 'a', encoding='utf-8') as f: | ||
| f.write(f"[HTTP] {path_str} | Python: {delta_mb:.2f} MB | Peak: {peak_mb:.2f} MB | RSS: {rss_delta_mb:.2f} MB | Total RSS: {rss_after/1024:.2f} MB\n") | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
General fix: avoid empty except blocks that only pass. Either (a) narrow the exception type and add a comment explaining why it’s safe to ignore, or (b) log the exception (or otherwise handle it) while still preventing it from propagating if that’s desired.
Best fix here without changing existing functionality: keep the “don’t break the request” behavior but add lightweight reporting using the existing check_send_notify helper already imported in this file. That preserves the current non‑fatal behavior while making failures visible. Concretely:
- For the
except Exception:aroundresource.getrusageat lines 110–113 and 165–169, we can add a clarifying comment and callcheck_send_notifywith a short message indicating RSS collection failed, includingexc_info=Trueso details go into logs. - For the
except Exception:around writing to/tmp/deceptgold_memory_debug.logat lines 176–180, likewise callcheck_send_notifyto record that memory debug logging failed, again withexc_info=True.
We can’t change imports except to use what’s already there; check_send_notify is already imported on line 7, so no new imports are needed. All changes are confined to deceptgold/src/deceptgold/helper/opencanary/help_opencanary.py in the shown regions.
| @@ -110,7 +110,8 @@ | ||
| try: | ||
| rss_before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: | ||
| pass | ||
| # Best-effort: do not fail request handling if RSS collection fails, but log it. | ||
| check_send_notify("Failed to collect RSS (before request).", exc_info=True) | ||
|
|
||
| if tracemalloc.is_tracing(): | ||
| mem_before, _ = tracemalloc.get_traced_memory() | ||
| @@ -166,7 +167,8 @@ | ||
| try: | ||
| rss_after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss | ||
| except Exception: | ||
| pass | ||
| # Best-effort: do not fail request handling if RSS collection fails, but log it. | ||
| check_send_notify("Failed to collect RSS (after request).", exc_info=True) | ||
|
|
||
| if tracemalloc.is_tracing() and mem_before is not None: | ||
| mem_after, peak = tracemalloc.get_traced_memory() | ||
| @@ -177,7 +179,8 @@ | ||
| with open('/tmp/deceptgold_memory_debug.log', 'a', encoding='utf-8') as f: | ||
| f.write(f"[HTTP] {path_str} | Python: {delta_mb:.2f} MB | Peak: {peak_mb:.2f} MB | RSS: {rss_delta_mb:.2f} MB | Total RSS: {rss_after/1024:.2f} MB\n") | ||
| except Exception: | ||
| pass | ||
| # Ignore failures writing debug log, but record them for diagnostics. | ||
| check_send_notify("Failed to write memory debug log.", exc_info=True) | ||
| gc.collect() | ||
|
|
||
| wrapper.__dg_forwarded_patch__ = True |
| continue | ||
| setattr(cls, method_name, wrap_method(original)) | ||
|
|
||
| _forwarded_patch_applied = True |
Check notice
Code scanning / CodeQL
Unused global variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, to fix an "unused global variable" that is only used internally by one function, you either remove it if it’s unnecessary, or convert it to a function-local construct (such as an attribute on the function or a closure variable) so it no longer exists as a module-level global. This keeps the state where it is needed while avoiding an unnecessary global declaration.
Here, _forwarded_patch_applied is only used to ensure _patch_http_logging() runs its patching logic once. We can remove the module-level assignment on line 21 and the global statement on line 84, and instead use a function attribute, e.g. _patch_http_logging._forwarded_patch_applied. Inside the function, we initialize this attribute on first use, check it early to short‑circuit subsequent calls, and set it to True after we finish applying patches. This preserves the "run once" behavior with the same semantics, without exposing a separate module-level variable.
Concretely:
-
Delete the line
_forwarded_patch_applied = Falseat module scope (around line 21). -
In
_patch_http_logging(), removeglobal _forwarded_patch_applied. -
At the start of
_patch_http_logging(), add logic to initialize and check a function attribute, e.g.:if getattr(_patch_http_logging, "_forwarded_patch_applied", False): return
-
At the end of
_patch_http_logging(), replace_forwarded_patch_applied = Truewith:_patch_http_logging._forwarded_patch_applied = True
No new imports or external dependencies are required.
| @@ -18,7 +18,7 @@ | ||
|
|
||
|
|
||
|
|
||
| _forwarded_patch_applied = False | ||
|
|
||
| _trace_enabled = bool(int(os.environ.get("DECEPTGOLD_TRACE_ALLOC", "0") or 0)) | ||
| _trace_every = max(int(os.environ.get("DECEPTGOLD_TRACE_EVERY", "0") or 0), 0) | ||
| _trace_top_n = max(int(os.environ.get("DECEPTGOLD_TRACE_TOP", "5") or 5), 1) | ||
| @@ -81,8 +81,9 @@ | ||
|
|
||
|
|
||
| def _patch_http_logging(): | ||
| global _forwarded_patch_applied | ||
| if _forwarded_patch_applied: | ||
| # Use a function attribute to ensure the patch is only applied once, | ||
| # instead of relying on a module-level global variable. | ||
| if getattr(_patch_http_logging, "_forwarded_patch_applied", False): | ||
| return | ||
|
|
||
| try: | ||
| @@ -199,7 +200,7 @@ | ||
| continue | ||
| setattr(cls, method_name, wrap_method(original)) | ||
|
|
||
| _forwarded_patch_applied = True | ||
| _patch_http_logging._forwarded_patch_applied = True | ||
|
|
||
|
|
||
| def start_opencanary_internal(force_no_wallet='force_no_wallet=False', debug=False): |
| if new_ip: | ||
| self._cached_public_ip = new_ip | ||
| self._public_ip_last_update = now | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, to fix an empty except block, you should either (a) narrow the exception type and handle it explicitly, or (b) at least log or otherwise record the error so it is not completely hidden. Only in very rare, well-documented cases should an exception be silently ignored, and then an explanatory comment is needed.
Here, the best fix that preserves existing functionality is to keep the current behavior (failure to get the public IP should not break the honeypot) but log the exception instead of just passing. This keeps the honeypot running even if _get_machine_public_ip fails, while giving operators visibility into recurring errors. We also avoid changing control flow or raising new exceptions to callers.
Concretely, in deceptgold/src/deceptgold/helper/web3honeypot/base.py, in method _update_public_ip_cache, replace the except Exception: pass block with code that captures the exception as e and logs it through the existing self.logger if available, otherwise falls back to the standard logging module already imported at the top of the file. We do not need new imports or dependencies.
| @@ -121,8 +121,18 @@ | ||
| if new_ip: | ||
| self._cached_public_ip = new_ip | ||
| self._public_ip_last_update = now | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
| # Log and ignore failures to update public IP; honeypot operation should continue. | ||
| if hasattr(self, "logger") and self.logger: | ||
| try: | ||
| self.logger.log({ | ||
| "logdata": f"Failed to update public IP in {self.service_name}: {e}", | ||
| "logtype": 5001, | ||
| }) | ||
| except Exception: | ||
| logging.exception("Failed to log public IP update error") | ||
| else: | ||
| logging.exception("Failed to update public IP cache") | ||
|
|
||
| def log_attack(self, attack_type: str, details: Dict[str, Any], severity: str = "medium"): | ||
| """Log an attack attempt""" |
No description provided.