Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/debug_toolbar/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class DebugToolbarConfig:
panel_display_depth: Max depth for nested data rendering. Defaults to 10.
panel_display_max_items: Max items to show in arrays/objects. Defaults to 100.
panel_display_max_string: Max string length before truncation. Defaults to 1000.
profiler_backend: Profiling backend: "cprofile", "pyinstrument", or "tachyon". Defaults to "cprofile".
profiler_top_functions: Max functions shown in the profiling panel. Defaults to 50.
profiler_sort_by: Sort order for profiling results. Defaults to "cumulative".
profiler_tachyon_interval_usec: Tachyon sampling interval in microseconds. Defaults to 1000.
enable_flamegraph: Whether to generate flame graph data. Defaults to True.
async_profiler_backend: Async profiler backend. "auto" selects best available.
async_blocking_threshold_ms: Threshold for blocking call detection. Defaults to 100.
async_enable_blocking_detection: Whether to detect blocking calls. Defaults to True.
Expand Down Expand Up @@ -69,6 +74,12 @@ class DebugToolbarConfig:
panel_display_max_items: int = 100
panel_display_max_string: int = 1000

profiler_backend: Literal["cprofile", "pyinstrument", "tachyon"] = "cprofile"
profiler_top_functions: int = 50
profiler_sort_by: str = "cumulative"
profiler_tachyon_interval_usec: int = 1000
enable_flamegraph: bool = True

async_profiler_backend: Literal["taskfactory", "yappi", "auto"] = "auto"
async_blocking_threshold_ms: float = 100.0
async_enable_blocking_detection: bool = True
Expand Down
33 changes: 33 additions & 0 deletions tests/unit/test_profiling_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,39 @@ def test_initialization_defaults(self, mock_toolbar: MagicMock) -> None:
assert panel._profiling_overhead == 0.0


class TestProfilingPanelWithRealConfig:
"""Profiling options documented in the configuration guide must be accepted by every config class."""

@pytest.mark.parametrize(
"config_path",
[
"debug_toolbar.core.config:DebugToolbarConfig",
"debug_toolbar.litestar.config:LitestarDebugToolbarConfig",
"debug_toolbar.starlette.config:StarletteDebugToolbarConfig",
"debug_toolbar.fastapi.config:FastAPIDebugToolbarConfig",
],
)
def test_panel_uses_profiler_options_from_config(self, config_path: str) -> None:
module_name, class_name = config_path.split(":")
config_class = getattr(pytest.importorskip(module_name), class_name)
config = config_class(
profiler_backend="cprofile",
profiler_top_functions=7,
profiler_sort_by="tottime",
profiler_tachyon_interval_usec=500,
enable_flamegraph=False,
)
toolbar = MagicMock()
toolbar.config = config

panel = ProfilingPanel(toolbar)

assert panel._backend == "cprofile"
assert panel._top_functions == 7
assert panel._sort_by == "tottime"
assert panel._enable_flamegraph is False


class TestProfilingPanelBackendSelection:
"""Tests for backend selection logic."""

Expand Down
Loading