Skip to content
Open
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
2 changes: 1 addition & 1 deletion build.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def _normalize_arch(machine: str) -> Optional[str]:

def _normalize_os() -> Optional[str]:
system = platform.system().lower()
if system == "linux":
if system in {"linux", "android"}:
return "linux"
if system == "darwin":
return "macos"
Expand Down
86 changes: 86 additions & 0 deletions diagnostic/build-2b54872c.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"generated_at": "2026-06-20T05:45:33.867184+00:00",
"commit": "2b54872c",
"diagnostic_logd": "diagnostic/build-2b54872c.logd",
"diagnostic_logd_error": null,
"chunked": false,
"chunk_size_bytes": null,
"password": "7af65ddb5df46a8c00ab",
"decrypt_command": "encryptly unpack diagnostic/build-2b54872c.logd <outdir> --password 7af65ddb5df46a8c00ab",
"total_modules": 10,
"passed": 1,
"failed": 9,
"modules": [
{
"name": "backend",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'cargo'"
},
{
"name": "frontend",
"status": "FAIL",
"elapsed_seconds": 1.434,
"artifact": null,
"output": "> tent-frontend@0.0.0 build\n> tsc -b && vite build\nsh: 1: tsc: not found"
},
{
"name": "market",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'go'"
},
{
"name": "frailbox",
"status": "PASS",
"elapsed_seconds": 0.063,
"artifact": "/data/data/com.termux/files/home/weilixiong-zeroeye/frailbox/frailbox",
"output": "make: Nothing to be done for 'all'."
},
{
"name": "engine",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'cmake'"
},
{
"name": "compliance",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'javac'"
},
{
"name": "v2-market-stream",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'ruby'"
},
{
"name": "nfc-scanner",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'luac'"
},
{
"name": "openapi-haskell",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'ghc'"
},
{
"name": "openapi-tools",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'luac'"
}
],
"pr_note": "Include the encrypted diagnostic logd artifact(s): diagnostic/build-2b54872c.logd. The encrypted .logd is the required diagnostic content for PR review; this JSON file is metadata. Maintainers may ask you to remove these diagnostic artifacts before merging."
}
Binary file added diagnostic/build-2b54872c.logd
Binary file not shown.
Binary file modified tools/encryptly/linux-arm64/encryptly
Binary file not shown.
30 changes: 26 additions & 4 deletions tools/monitoring_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import argparse
import json
import os
import re
import sys
import time
import urllib.request
Expand Down Expand Up @@ -78,7 +79,7 @@
},
{
"name": "HighMemoryUsage",
"expr": "process_resident_memory_bytes / process_resident_memory_bytes > 0.9",
"expr": "process_resident_memory_bytes / machine_memory_bytes > 0.9",
"duration": "10m",
"severity": "warning",
"summary": "High memory usage on {{$labels.instance}}",
Expand Down Expand Up @@ -372,6 +373,26 @@ def backup_monitoring_config(output_dir: str, prometheus_url: str,
return True


def validate_alert_expressions(rules: List[Dict[str, Any]]) -> bool:
"""
Validate alert rules configuration for self-dividing expressions.
Returns False if any self-dividing expressions are found, True otherwise.
"""
self_dividing_pattern = re.compile(r'\b(\w+)\s*/\s*\1\b')
all_valid = True
for rule in rules:
name = rule.get("name")
expr = rule.get("expr")
if expr:
match = self_dividing_pattern.search(expr)
if match:
print(f" ✗ Validation Alert: Alert rule '{name}' has a self-dividing expression: '{expr}' (divided by '{match.group(1)}')")
all_valid = False
else:
print(f" ✓ Alert rule '{name}' expression is valid")
return all_valid


def parse_args():
parser = argparse.ArgumentParser(description="Monitoring setup tool")
parser.add_argument("--prometheus-url", default=DEFAULT_PROMETHEUS_URL)
Expand Down Expand Up @@ -429,19 +450,20 @@ def main():

if args.validate:
print("Validating monitoring configuration...")
alerts_ok = validate_alert_expressions(RECOMMENDED_ALERT_RULES)
configs_to_check = [
args.prometheus_url,
args.alertmanager_url,
]
all_ok = True
endpoints_ok = True
for url in configs_to_check:
result = http_request("GET", f"{url}/-/healthy")
if result:
print(f" {url}: OK")
else:
print(f" {url}: FAILED")
all_ok = False
return 0 if all_ok else 1
endpoints_ok = False
return 0 if (alerts_ok and endpoints_ok) else 1

parser.print_help()
return 0
Expand Down
55 changes: 55 additions & 0 deletions tools/test_monitoring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
Unit tests for monitoring configuration and alert rule validations.
"""

import sys
import os
import unittest

# Add parent directory to path so we can import tools.monitoring_setup
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from tools import monitoring_setup

class TestMonitoringValidation(unittest.TestCase):
"""
Test suite for checking monitoring alert rule expressions and validation helper.
"""

def test_self_dividing_detection(self):
"""
Verify that self-dividing PromQL expressions are flagged and correct ones pass.
"""
# Self-dividing expression (should fail validation)
invalid_rules = [
{
"name": "InvalidMemoryRule",
"expr": "process_resident_memory_bytes / process_resident_memory_bytes > 0.9"
}
]

# Valid expression (should pass validation)
valid_rules = [
{
"name": "ValidMemoryRule",
"expr": "process_resident_memory_bytes / machine_memory_bytes > 0.9"
},
{
"name": "ValidCpuRule",
"expr": "avg by(instance) (rate(process_cpu_seconds_total[5m])) > 0.8"
}
]

# Check validation outcomes
self.assertFalse(monitoring_setup.validate_alert_expressions(invalid_rules))
self.assertTrue(monitoring_setup.validate_alert_expressions(valid_rules))

def test_recommended_rules_valid(self):
"""
Ensure all production alert rules defined in monitoring_setup are valid.
"""
# Run validation on the actual recommended alert rules in the codebase
rules = monitoring_setup.RECOMMENDED_ALERT_RULES
self.assertTrue(monitoring_setup.validate_alert_expressions(rules))

if __name__ == '__main__':
unittest.main()