diff --git a/backend/app/config.py b/backend/app/config.py index 93d5e4a..31ef29c 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -15,5 +15,7 @@ class Settings(BaseSettings): APP_ENV: str = "development" DEBUG: bool = False + SQLALCHEMY_LOG: bool = False + settings = Settings() diff --git a/backend/app/main.py b/backend/app/main.py index 3239193..c470a4f 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -17,6 +17,12 @@ logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', ) +from app.config import settings # noqa: E402 +if not settings.SQLALCHEMY_LOG: + logging.getLogger("sqlalchemy.engine").setLevel(logging.WARNING) + logging.getLogger("sqlalchemy.pool").setLevel(logging.WARNING) + logging.getLogger("sqlalchemy.dialects").setLevel(logging.WARNING) + @asynccontextmanager async def lifespan(app: FastAPI): diff --git a/backend/app/services/ssh.py b/backend/app/services/ssh.py index 8da8506..923e946 100644 --- a/backend/app/services/ssh.py +++ b/backend/app/services/ssh.py @@ -351,11 +351,27 @@ async def run_command( last_result: Optional[SSHResult] = None for i, opt in enumerate(options): + if opt.type == "key": + logger.info( + "SSH attempt %d/%d for %s — key: user=%s key_path=%s", + i + 1, len(options), device.ip, opt.username, opt.key_path, + ) + else: + masked = (opt.password[:1] + "***" + opt.password[-1:]) if len(opt.password) > 2 else "***" + logger.info( + "SSH attempt %d/%d for %s — password: user=%s password=%s", + i + 1, len(options), device.ip, opt.username, masked, + ) + result = await _try_connect(device.ip, port, opt, command, timeout) if result.auth_ok: # Connection was established — auth succeeded. # Return the result regardless of exit_code (command may have failed, not auth). + logger.info( + "SSH auth succeeded for %s with %s(%s)", + device.ip, opt.type, opt.username, + ) if db: await _save_last_auth(device, db, opt) return result @@ -370,7 +386,7 @@ async def run_command( pass last_result = result - logger.debug( + logger.info( "SSH auth failed for %s with %s(%s): %s", device.ip, opt.type, opt.username, result.error, ) @@ -409,10 +425,23 @@ async def run_command_direct_with_options( """Try multiple auth options for a non-Device host (e.g. rack PC during discovery).""" async with _global_sem: last_result: Optional[SSHResult] = None - for opt in options: + for i, opt in enumerate(options): + if opt.type == "key": + logger.info( + "SSH attempt %d/%d for %s — key: user=%s key_path=%s", + i + 1, len(options), host, opt.username, opt.key_path, + ) + else: + masked = (opt.password[:1] + "***" + opt.password[-1:]) if len(opt.password) > 2 else "***" + logger.info( + "SSH attempt %d/%d for %s — password: user=%s password=%s", + i + 1, len(options), host, opt.username, masked, + ) result = await _try_connect(host, port, opt, command, timeout) - if result.success: + if result.auth_ok: + logger.info("SSH auth succeeded for %s with %s(%s)", host, opt.type, opt.username) return result + logger.info("SSH auth failed for %s with %s(%s): %s", host, opt.type, opt.username, result.error) last_result = result if last_result: last_result.error = f"All auth methods exhausted. Last error: {last_result.error}"