feat(daemon,sdk,telemetry): add sandbox memory cache metric and Analy… - #5119
feat(daemon,sdk,telemetry): add sandbox memory cache metric and Analy…#5119MDzaja wants to merge 1 commit into
Conversation
…tics API clients Signed-off-by: MDzaja <mirkodzaja0@gmail.com>
|
View your CI Pipeline Execution ↗ for commit b4a0f88
💡 Dealing with memory or CPU issues? See memory and CPU details with the resource usage add-on ↗. ☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
9 issues found across 177 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="libs/analytics-api-client-python/setup.py">
<violation number="1" location="libs/analytics-api-client-python/setup.py:35">
P2: Author/email set to OpenAPI Generator community placeholder instead of Daytona Platforms Inc. This is a first-party publishable package — metadata should match the existing Python client convention so published package attribution is correct.</violation>
<violation number="2" location="libs/analytics-api-client-python/setup.py:42">
P2: Missing `license="Apache-2.0"` in setup(). The existing first-party Python client specifies this. Without it, published package metadata omits the license, which is a quality gap for a publishable package.</violation>
</file>
<file name="libs/analytics-api-client-java/src/main/java/io/daytona/analytics/api/client/ApiResponse.java">
<violation number="1" location="libs/analytics-api-client-java/src/main/java/io/daytona/analytics/api/client/ApiResponse.java:42">
P3: Javadoc typo: "response bod" should be "response body".</violation>
</file>
<file name="libs/analytics-api-client-python/.gitignore">
<violation number="1" location="libs/analytics-api-client-python/.gitignore:45">
P3: Typo in gitignore pattern: `*,cover` should be `*.cover` (dot instead of comma). The current pattern never matches any real coverage output file.</violation>
</file>
<file name="libs/analytics-api-client-python/daytona_analytics_api_client/models/models_usage_period.py">
<violation number="1" location="libs/analytics-api-client-python/daytona_analytics_api_client/models/models_usage_period.py:23">
P3: `Optional` is imported twice (lines 16 and 19). Merge `Set` into the first import and drop the second line to eliminate the flake8 F811 violation.</violation>
</file>
<file name="libs/analytics-api-client-ruby/.rubocop.yml">
<violation number="1" location="libs/analytics-api-client-ruby/.rubocop.yml:4">
P2: RuboCop `TargetRubyVersion` is set to `2.4` but the gemspec requires `>= 2.7`. This overrides auto-detection and prevents RuboCop from applying cops relevant to 2.7+ features, while keeping obsolete 2.4-specific rules active.</violation>
</file>
<file name="libs/analytics-api-client-go/client.go">
<violation number="1" location="libs/analytics-api-client-go/client.go:216">
P3: Float64 query parameters are formatted with 32‑bit precision, which truncates float64 values when they’re added to query strings. Split the float32 and float64 cases so float64 uses 64‑bit formatting.</violation>
</file>
<file name="libs/analytics-api-client-python-async/tox.ini">
<violation number="1" location="libs/analytics-api-client-python-async/tox.ini:9">
P2: The tox test command is configured to run pytest even though this package has no tests, which makes tox fail by default with pytest exit code 5 (no tests collected).</violation>
</file>
<file name="libs/analytics-api-client-java/src/main/java/io/daytona/analytics/api/client/auth/HttpBearerAuth.java">
<violation number="1" location="libs/analytics-api-client-java/src/main/java/io/daytona/analytics/api/client/auth/HttpBearerAuth.java:40">
P2: HttpBearerAuth.getBearerToken() throws NullPointerException when called before tokenSupplier is set.
The field `tokenSupplier` is never initialized (defaults to null), so calling `getBearerToken()` before `setBearerToken(...)` will crash with NPE. The `applyToParams` method in the same class handles a null supplier safely via `Optional.ofNullable`, making this an inconsistency that will surprise callers using the public getter.</violation>
</file>
Note: This PR contains a large number of files. cubic only reviews up to 100 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
| install_requires=REQUIRES, | ||
| packages=find_packages(exclude=["test", "tests"]), | ||
| include_package_data=True, | ||
| long_description_content_type='text/markdown', |
There was a problem hiding this comment.
P2: Missing license="Apache-2.0" in setup(). The existing first-party Python client specifies this. Without it, published package metadata omits the license, which is a quality gap for a publishable package.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-python/setup.py, line 42:
<comment>Missing `license="Apache-2.0"` in setup(). The existing first-party Python client specifies this. Without it, published package metadata omits the license, which is a quality gap for a publishable package.</comment>
<file context>
@@ -0,0 +1,47 @@
+ install_requires=REQUIRES,
+ packages=find_packages(exclude=["test", "tests"]),
+ include_package_data=True,
+ long_description_content_type='text/markdown',
+ long_description="""\
+ Daytona Analytics API - Read-only telemetry and usage data. Authenticated via Daytona API keys or JWT tokens.
</file context>
| author="OpenAPI Generator community", | ||
| author_email="team@openapitools.org", |
There was a problem hiding this comment.
P2: Author/email set to OpenAPI Generator community placeholder instead of Daytona Platforms Inc. This is a first-party publishable package — metadata should match the existing Python client convention so published package attribution is correct.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-python/setup.py, line 35:
<comment>Author/email set to OpenAPI Generator community placeholder instead of Daytona Platforms Inc. This is a first-party publishable package — metadata should match the existing Python client convention so published package attribution is correct.</comment>
<file context>
@@ -0,0 +1,47 @@
+ name=NAME,
+ version=VERSION,
+ description="Daytona Analytics API",
+ author="OpenAPI Generator community",
+ author_email="team@openapitools.org",
+ url="",
</file context>
| author="OpenAPI Generator community", | |
| author_email="team@openapitools.org", | |
| author="Daytona Platforms Inc.", | |
| author_email="support@daytona.com", |
| # This file is based on https://github.com/rails/rails/blob/master/.rubocop.yml (MIT license) | ||
| # Automatically generated by OpenAPI Generator (https://openapi-generator.tech) | ||
| AllCops: | ||
| TargetRubyVersion: 2.4 |
There was a problem hiding this comment.
P2: RuboCop TargetRubyVersion is set to 2.4 but the gemspec requires >= 2.7. This overrides auto-detection and prevents RuboCop from applying cops relevant to 2.7+ features, while keeping obsolete 2.4-specific rules active.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-ruby/.rubocop.yml, line 4:
<comment>RuboCop `TargetRubyVersion` is set to `2.4` but the gemspec requires `>= 2.7`. This overrides auto-detection and prevents RuboCop from applying cops relevant to 2.7+ features, while keeping obsolete 2.4-specific rules active.</comment>
<file context>
@@ -0,0 +1,148 @@
+# This file is based on https://github.com/rails/rails/blob/master/.rubocop.yml (MIT license)
+# Automatically generated by OpenAPI Generator (https://openapi-generator.tech)
+AllCops:
+ TargetRubyVersion: 2.4
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
+ # to ignore them, so only the ones explicitly set in this file are enabled.
</file context>
| -r{toxinidir}/test-requirements.txt | ||
|
|
||
| commands= | ||
| pytest --cov=daytona_analytics_api_client_async |
There was a problem hiding this comment.
P2: The tox test command is configured to run pytest even though this package has no tests, which makes tox fail by default with pytest exit code 5 (no tests collected).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-python-async/tox.ini, line 9:
<comment>The tox test command is configured to run pytest even though this package has no tests, which makes tox fail by default with pytest exit code 5 (no tests collected).</comment>
<file context>
@@ -0,0 +1,9 @@
+ -r{toxinidir}/test-requirements.txt
+
+commands=
+ pytest --cov=daytona_analytics_api_client_async
</file context>
| * @return The bearer token | ||
| */ | ||
| public String getBearerToken() { | ||
| return tokenSupplier.get(); |
There was a problem hiding this comment.
P2: HttpBearerAuth.getBearerToken() throws NullPointerException when called before tokenSupplier is set.
The field tokenSupplier is never initialized (defaults to null), so calling getBearerToken() before setBearerToken(...) will crash with NPE. The applyToParams method in the same class handles a null supplier safely via Optional.ofNullable, making this an inconsistency that will surprise callers using the public getter.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-java/src/main/java/io/daytona/analytics/api/client/auth/HttpBearerAuth.java, line 40:
<comment>HttpBearerAuth.getBearerToken() throws NullPointerException when called before tokenSupplier is set.
The field `tokenSupplier` is never initialized (defaults to null), so calling `getBearerToken()` before `setBearerToken(...)` will crash with NPE. The `applyToParams` method in the same class handles a null supplier safely via `Optional.ofNullable`, making this an inconsistency that will surprise callers using the public getter.</comment>
<file context>
@@ -0,0 +1,75 @@
+ * @return The bearer token
+ */
+ public String getBearerToken() {
+ return tokenSupplier.get();
+ }
+
</file context>
| return tokenSupplier.get(); | |
| public String getBearerToken() { | |
| return Optional.ofNullable(tokenSupplier).map(Supplier::get).orElse(null); | |
| } |
| * | ||
| * @param statusCode The status code of HTTP response | ||
| * @param headers The headers of HTTP response | ||
| * @param data The object deserialized from response bod |
There was a problem hiding this comment.
P3: Javadoc typo: "response bod" should be "response body".
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-java/src/main/java/io/daytona/analytics/api/client/ApiResponse.java, line 42:
<comment>Javadoc typo: "response bod" should be "response body".</comment>
<file context>
@@ -0,0 +1,76 @@
+ *
+ * @param statusCode The status code of HTTP response
+ * @param headers The headers of HTTP response
+ * @param data The object deserialized from response bod
+ */
+ public ApiResponse(int statusCode, Map<String, List<String>> headers, T data) {
</file context>
| .cache | ||
| nosetests.xml | ||
| coverage.xml | ||
| *,cover |
There was a problem hiding this comment.
P3: Typo in gitignore pattern: *,cover should be *.cover (dot instead of comma). The current pattern never matches any real coverage output file.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-python/.gitignore, line 45:
<comment>Typo in gitignore pattern: `*,cover` should be `*.cover` (dot instead of comma). The current pattern never matches any real coverage output file.</comment>
<file context>
@@ -0,0 +1,66 @@
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+venv/
</file context>
| *,cover | |
| *.cover |
| from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr | ||
| from typing import Any, ClassVar, Dict, List, Optional, Union | ||
| from pydantic import TypeAdapter | ||
| from typing import Optional, Set |
There was a problem hiding this comment.
P3: Optional is imported twice (lines 16 and 19). Merge Set into the first import and drop the second line to eliminate the flake8 F811 violation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-python/daytona_analytics_api_client/models/models_usage_period.py, line 23:
<comment>`Optional` is imported twice (lines 16 and 19). Merge `Set` into the first import and drop the second line to eliminate the flake8 F811 violation.</comment>
<file context>
@@ -0,0 +1,114 @@
+from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional, Union
+from pydantic import TypeAdapter
+from typing import Optional, Set
+from typing_extensions import Self
+
</file context>
| case reflect.Float32, reflect.Float64: | ||
| value = strconv.FormatFloat(v.Float(), 'g', -1, 32) |
There was a problem hiding this comment.
P3: Float64 query parameters are formatted with 32‑bit precision, which truncates float64 values when they’re added to query strings. Split the float32 and float64 cases so float64 uses 64‑bit formatting.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/analytics-api-client-go/client.go, line 216:
<comment>Float64 query parameters are formatted with 32‑bit precision, which truncates float64 values when they’re added to query strings. Split the float32 and float64 cases so float64 uses 64‑bit formatting.</comment>
<file context>
@@ -0,0 +1,656 @@
+ case reflect.Uint, reflect.Uint8, reflect.Uint16,
+ reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ value = strconv.FormatUint(v.Uint(), 10)
+ case reflect.Float32, reflect.Float64:
+ value = strconv.FormatFloat(v.Float(), 'g', -1, 32)
+ case reflect.Bool:
</file context>
| case reflect.Float32, reflect.Float64: | |
| value = strconv.FormatFloat(v.Float(), 'g', -1, 32) | |
| case reflect.Float32: | |
| value = strconv.FormatFloat(v.Float(), 'g', -1, 32) | |
| case reflect.Float64: | |
| value = strconv.FormatFloat(v.Float(), 'g', -1, 64) |
rajpratham1
left a comment
There was a problem hiding this comment.
Thanks for the significant work on this feature. The overall direction looks valuable, but I don't think this PR is in a reviewable state yet.
My main concerns are:
This PR combines multiple independent changes (daemon metrics, telemetry APIs, SDK updates, generated clients, release workflow, documentation, and dashboard changes) into a single 33k+ line change set.
Most of the added files appear to be generated SDK code, which makes it difficult to identify and review the actual implementation logic.
Mixing generated artifacts with handwritten code significantly increases review complexity and future maintenance.
Release workflow changes should ideally be reviewed independently from the feature itself.
I'd recommend splitting this into smaller PRs, for example:
Core daemon/telemetry implementation.
OpenAPI specification updates.
Generated SDK/client updates.
Dashboard/UI changes.
Documentation and release workflow updates.
Breaking the work into focused PRs will make it much easier to validate correctness, review changes thoroughly, and reduce regression risk.
Summary
Expands per-sandbox telemetry coverage:
daytona.sandbox.memory.cachegauge (page cache, bytes) to the metrics emitted by the sandbox daemon.Changes
New metric —
daytona.sandbox.memory.cachelibs/common-go/pkg/telemetry/metrics.go— register the gauge inregisterUsageMetricsas anInt64ObservableGauge, observed from the existingReadCgroupMemCacheBytes(cgroupV2)helper (already used by the live system-metrics endpoint; no new cgroup logic).apps/dashboard/src/constants/metrics.ts— display name "Memory Cache".apps/docs/.../observability/otel-collection.mdx— document the metric.Analytics API clients (Go / Python / Python-async / Ruby / Java)
libs/analytics-api-client-{go,python,python-async,ruby,java}, each with agenerate:api-clienttarget that reuses the sharedhack/<lang>-client/post-processing scripts and templates (no duplicated tooling).go.work, rootpyproject.toml(+poetry.lock),Gemfile,package.json(excluded from the default API-spec generation run, consistent with the existing TypeScript analytics/billing clients).release.yaml(Go module tag) andsdk_publish.yaml(publish matrix entries for the Python/Ruby/Java packages).Why it's safe
memory.statper sampling tick — no OOM, no new shared state, no new race.Verification
go build/go vet/go test ./pkg/telemetry/...clean.otel_daytona_sandbox_memory_cache_bytes, real value observed).nxdiscovers all new projects;poetry checkvalid; workflows validated.Rollout
daytona.sandbox.memory.cacheappears via the telemetry API — then roll out fleet-wide.Summary by cubic
Adds a new sandbox memory cache metric and ships Analytics API client libraries for Go, Python (sync and async), Ruby, and Java to let all SDKs query telemetry and usage.
New Features
daytona.sandbox.memory.cache(bytes) using the existing cgroup reader; adds Dashboard label “Memory Cache” and docs entry.analytics-api-client-go,analytics-api-client-python,analytics-api-client-python-async,analytics-api-client-ruby,analytics-api-client-java.Dependencies
libs/analytics-api-client-goinrelease.yaml; add Python/Ruby/Java analytics clients to thesdk_publish.yamlmatrix../libs/analytics-api-client-goingo.work; adddaytona_analytics_api_clientto theGemfile.Written for commit b4a0f88. Summary will update on new commits.