(verbose: bool = False)
| 151 | |
| 152 | |
| 153 | def _setup_logging(verbose: bool = False) -> None: |
| 154 | level = logging.DEBUG if verbose else logging.INFO |
| 155 | _install_secret_log_record_factory() |
| 156 | handler = logging.StreamHandler(sys.stderr) |
| 157 | handler.addFilter(_SecretRedactionFilter()) |
| 158 | redaction_filter = _SecretRedactionFilter() |
| 159 | handler.addFilter(redaction_filter) |
| 160 | logging.basicConfig( |
| 161 | level=level, |
| 162 | format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", |
| 163 | handlers=[handler], |
| 164 | force=True, |
| 165 | ) |
| 166 | root_logger = logging.getLogger() |
| 167 | root_logger.addFilter(redaction_filter) |
| 168 | for existing_handler in root_logger.handlers: |
| 169 | existing_handler.addFilter(redaction_filter) |
| 170 | # httpx logs full request URLs at INFO, including query parameters. |
| 171 | # Keep third-party request traces quiet; NanoResearch logs stage progress separately. |
| 172 | logging.getLogger("httpx").setLevel(logging.WARNING) |
| 173 | logging.getLogger("httpcore").setLevel(logging.WARNING) |
| 174 | |
| 175 | |
| 176 | def _load_config_safe(config_path: Path | None) -> ResearchConfig: |
no test coverage detected