health endpoint

This commit is contained in:
Joel Krauska
2025-11-03 15:05:28 -08:00
parent 991794ed3d
commit 7d0d704412
4 changed files with 126 additions and 33 deletions
+34 -3
View File
@@ -288,15 +288,46 @@ Request: `/api/lang?section=chat`
---
## 9. Version API
## 9. Health Check API
### GET `/health`
Health check endpoint for monitoring, load balancers, and orchestration systems.
**Response Example (Healthy)**
```json
{
"status": "healthy",
"timestamp": "2025-11-03T14:30:00.123456Z",
"version": "2.0.8",
"git_revision": "6416978",
"database": "connected"
}
```
**Response Example (Unhealthy)**
Status Code: `503 Service Unavailable`
```json
{
"status": "unhealthy",
"timestamp": "2025-11-03T14:30:00.123456Z",
"version": "2.0.8",
"git_revision": "6416978",
"database": "disconnected"
}
```
---
## 10. Version API
### GET `/version`
Returns version information including semver and git revision.
Returns detailed version information including semver, release date, and git revision.
**Response Example**
```json
{
"version": "2.0.8 ~ 10-22-25",
"version": "2.0.8",
"release_date": "2025-10-22",
"git_revision": "6416978a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q",
"git_revision_short": "6416978"
}
+1
View File
@@ -9,5 +9,6 @@ These documents are intended for developers, contributors, and advanced users wh
- [ALEMBIC_SETUP.md](ALEMBIC_SETUP.md) - Database migration setup and management
- [TIMESTAMP_MIGRATION.md](TIMESTAMP_MIGRATION.md) - Details on timestamp schema changes
- [API_Documentation.md](API_Documentation.md) - REST API endpoints and usage
- [CODE_IMPROVEMENTS.md](CODE_IMPROVEMENTS.md) - Suggested code improvements and refactoring ideas
For initial setup and basic usage instructions, please see the main [README.md](../README.md) in the root directory.
+56
View File
@@ -0,0 +1,56 @@
"""Version information for MeshView."""
import subprocess
from pathlib import Path
__version__ = "3.0.0"
__release_date__ = "2025-11-05"
def get_git_revision():
"""Get the current git revision hash."""
try:
repo_dir = Path(__file__).parent.parent
result = subprocess.run(
["git", "rev-parse", "HEAD"],
capture_output=True,
text=True,
check=True,
cwd=repo_dir,
)
return result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
return "unknown"
def get_git_revision_short():
"""Get the short git revision hash."""
try:
repo_dir = Path(__file__).parent.parent
result = subprocess.run(
["git", "rev-parse", "--short", "HEAD"],
capture_output=True,
text=True,
check=True,
cwd=repo_dir,
)
return result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
return "unknown"
def get_version_info():
"""Get complete version information."""
return {
"version": __version__,
"release_date": __release_date__,
"git_revision": get_git_revision(),
"git_revision_short": get_git_revision_short(),
}
# Cache git info at import time for performance
_git_revision = get_git_revision()
_git_revision_short = get_git_revision_short()
# Full version string for display
__version_string__ = f"{__version__} ~ {__release_date__}"
+35 -30
View File
@@ -19,9 +19,17 @@ from google.protobuf.message import Message
from jinja2 import Environment, PackageLoader, Undefined, select_autoescape
from markupsafe import Markup
from pandas import DataFrame
from sqlalchemy import text
from meshtastic.protobuf.portnums_pb2 import PortNum
from meshview import config, database, decode_payload, migrations, models, store
from meshview.__version__ import (
__version__,
__version_string__,
_git_revision,
_git_revision_short,
get_version_info,
)
logging.basicConfig(
level=logging.INFO,
@@ -31,7 +39,7 @@ logging.basicConfig(
logger = logging.getLogger(__name__)
SEQ_REGEX = re.compile(r"seq \d+")
SOFTWARE_RELEASE = "2.0.8 ~ 10-22-25"
SOFTWARE_RELEASE = __version_string__ # Keep for backward compatibility
CONFIG = config.CONFIG
env = Environment(loader=PackageLoader("meshview"), autoescape=select_autoescape())
@@ -1751,39 +1759,36 @@ async def api_lang(request):
return web.json_response(translations)
@routes.get("/health")
async def health_check(request):
"""Health check endpoint for monitoring and load balancers."""
health_status = {
"status": "healthy",
"timestamp": datetime.datetime.now(datetime.UTC).isoformat(),
"version": __version__,
"git_revision": _git_revision_short,
}
# Check database connectivity
try:
async with database.async_session() as session:
await session.execute(text("SELECT 1"))
health_status["database"] = "connected"
except Exception as e:
logger.error(f"Database health check failed: {e}")
health_status["database"] = "disconnected"
health_status["status"] = "unhealthy"
return web.json_response(health_status, status=503)
return web.json_response(health_status)
@routes.get("/version")
async def version_endpoint(request):
"""Return version information including semver and git revision."""
try:
# Get git revision hash
try:
result = subprocess.run(
["git", "rev-parse", "HEAD"],
capture_output=True,
text=True,
check=True,
cwd=os.path.dirname(__file__),
)
git_revision = result.stdout.strip()
# Also get short hash
result_short = subprocess.run(
["git", "rev-parse", "--short", "HEAD"],
capture_output=True,
text=True,
check=True,
cwd=os.path.dirname(__file__),
)
git_revision_short = result_short.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
git_revision = "unknown"
git_revision_short = "unknown"
return web.json_response({
"version": SOFTWARE_RELEASE,
"git_revision": git_revision,
"git_revision_short": git_revision_short,
})
version_info = get_version_info()
return web.json_response(version_info)
except Exception as e:
logger.error(f"Error in /version: {e}")
return web.json_response({"error": "Failed to fetch version info"}, status=500)