Skip to content

Commit 6878f62

Browse files
Package Size Analyzer Improvements (AI-5309) (#20330)
* basic status reporting * integration into ddev * clean commented code * add diff mode * add diff mode * final diff version * final diff version * Added timeline mode and uncompressed sizes (#5025) * Test ddev size status in GHA (by hijacking the slapr workflow) * Timeline mode * Try to fix job summaries * Try fixing the job summaries again * CI size status integration on master * types added * change --help * fix * fix typing * fix typing * fix types * fix types * fix typing * fix typing * fix typing * fix typing * fix tests for Windows * Fix tests * fix windows tests * Fix tests * Fix tests * fix windows tests * Final visualizations * Changelog * CI images integration and fixed typing * user errors and dep and int versions * user errors and dep and int versions * user errors and dep and int versions * fix timeline error * Adding version, and json and markdown formats * Fix test * simplify code * final fixes * fix ddev windows * fix lint * testing ddev tests on windows * initialize create_dashboard command * test * test * test * test * test * test * test * test * test * test * test * test * send metrics to dd * create-dashboard command * fixes * test gha * test gha * test gha * fixes * fixes * fixes * fix * getting commit timestamp * getting commit timestamp * Add commit timestamp * correct comments * correct comments * Change comments * Change number to constant * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Fix a comment * Change number to constant * Typing * Change format flags * change format input * Correct test-common * wip: Work in Progress * Commiting to test send-metrics * Commiting to test send-metrics * Commiting to test send-metrics * Commiting to test send-metrics * Commiting to test send-metrics * Commiting to test send-metrics * Commiting to test send-metrics * Fix typing * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Committing to test the send metrics * Lints * Fix tests * Changelog * Change create-dashboard help * Simplify output formats --------- Co-authored-by: Enrico Donnici <enrico.donnici@datadoghq.com>
1 parent 5dbed44 commit 6878f62

17 files changed

+1020
-713
lines changed

ddev/changelog.d/20330.added

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Added `ddev size create-dashboard` to visualize size metrics on the Datadog platform
2+
- Added `--to-dd-org` option to `ddev size status` to send metrics to Datadog

ddev/changelog.d/20330.changed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replaced multiple format flags with a single `--format` option in the `ddev size` command.

ddev/pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ dependencies = [
4242
"tqdm",
4343
"requests",
4444
"matplotlib",
45-
"squarify"
45+
"squarify",
46+
"datadog",
4647
]
4748
dynamic = ["version"]
4849

ddev/src/ddev/cli/size/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import click
66

7+
from ddev.cli.size.create_dashboard import create_dashboard
78
from ddev.cli.size.diff import diff
89
from ddev.cli.size.status import status
910
from ddev.cli.size.timeline import timeline
@@ -25,6 +26,7 @@ def size():
2526
size.add_command(status)
2627
size.add_command(diff)
2728
size.add_command(timeline)
29+
size.add_command(create_dashboard)
2830

2931
if __name__ == "__main__":
3032
size()
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import json
2+
from typing import Any
3+
4+
import click
5+
import requests
6+
7+
from ddev.cli.application import Application
8+
from ddev.cli.size.utils.common_funcs import get_org, get_valid_platforms
9+
10+
11+
@click.command()
12+
@click.option(
13+
"--dd-org",
14+
type=str,
15+
required=True,
16+
help="Datadog organization name taken from your config file e.g. 'default'",
17+
)
18+
@click.pass_obj
19+
def create_dashboard(
20+
app: Application,
21+
dd_org: str,
22+
) -> None:
23+
"""
24+
Creates a Datadog dashboard to visualize size metrics for integrations and dependencies.
25+
A new dashboard is created on each run. This command does not send data to Datadog.
26+
To send metrics, use: `ddev size status --to-dd-org <org>`.
27+
"""
28+
try:
29+
config_file_info = get_org(app, dd_org)
30+
if 'api_key' not in config_file_info:
31+
raise RuntimeError("No API key found in config file")
32+
if 'app_key' not in config_file_info:
33+
raise RuntimeError("No APP key found in config file")
34+
if 'site' not in config_file_info:
35+
raise RuntimeError("No site found in config file")
36+
headers = {
37+
"DD-API-KEY": config_file_info["api_key"],
38+
"DD-APPLICATION-KEY": config_file_info["app_key"],
39+
"Content-Type": "application/json",
40+
}
41+
42+
payload = {
43+
"title": "Disk Usage Status for Integrations and Dependencies",
44+
"layout_type": "ordered",
45+
"widgets": create_json(app),
46+
}
47+
48+
response = requests.post(
49+
f"https://api.{config_file_info['site']}/api/v1/dashboard",
50+
headers=headers,
51+
data=json.dumps(payload),
52+
)
53+
54+
resp_json = response.json()
55+
if "Forbidden" in str(resp_json.get("errors", [])):
56+
raise PermissionError("Access denied: your APP key doesn't have permission to create dashboards.")
57+
print(f"Dashboard URL: https://app.{config_file_info['site']}{resp_json['url']}")
58+
except Exception as e:
59+
app.abort(str(e))
60+
61+
62+
def create_json(app: Application) -> list[dict[str, Any]]:
63+
valid_platforms = get_valid_platforms(app.repo.path)
64+
widgets: list[dict[str, Any]] = []
65+
66+
for size_type in ["compressed", "uncompressed"]:
67+
for platform in valid_platforms:
68+
# Treemap widget
69+
widgets.append(
70+
{
71+
"definition": {
72+
"type": "treemap",
73+
"title": f"{size_type.capitalize()} sizes in {platform}",
74+
"requests": [
75+
{
76+
"queries": [
77+
{
78+
"data_source": "metrics",
79+
"name": "query2",
80+
"query": f"avg:datadog.agent_integrations.size_analyzer.{size_type}"
81+
f"{{platform:{platform}}} by {{name_type,name}}",
82+
"aggregator": "last",
83+
}
84+
],
85+
"response_format": "scalar",
86+
"style": {"palette": "classic"},
87+
"formulas": [
88+
{
89+
"formula": "query2",
90+
"number_format": {
91+
"unit": {
92+
"type": "canonical_unit",
93+
"unit_name": "byte_in_binary_bytes_family",
94+
}
95+
},
96+
}
97+
],
98+
}
99+
],
100+
}
101+
}
102+
)
103+
# Timeseries widget
104+
widgets.append(
105+
{
106+
"definition": {
107+
"title": f"Timeline of {size_type} sizes in {platform}",
108+
"type": "timeseries",
109+
"requests": [
110+
{
111+
"response_format": "timeseries",
112+
"queries": [
113+
{
114+
"name": "query1",
115+
"data_source": "metrics",
116+
"query": f"sum:datadog.agent_integrations.size_analyzer.{size_type}"
117+
f"{{platform:{platform}}}",
118+
}
119+
],
120+
"formulas": [
121+
{
122+
"formula": "query1",
123+
"number_format": {
124+
"unit": {
125+
"type": "canonical_unit",
126+
"unit_name": "byte_in_binary_bytes_family",
127+
}
128+
},
129+
}
130+
],
131+
"style": {
132+
"palette": "dog_classic",
133+
"order_by": "values",
134+
"line_type": "solid",
135+
"line_width": "normal",
136+
},
137+
"display_type": "line",
138+
}
139+
],
140+
}
141+
}
142+
)
143+
144+
return widgets

0 commit comments

Comments
 (0)