|
| 1 | +# DashboardSummary |
| 2 | + |
| 3 | +A small Java service that periodically queries InfluxDB metrics, asks Google Gemini to produce a short human‑friendly summary (2–4 sentences), and writes that summary back to InfluxDB for display on dashboards. |
| 4 | + |
| 5 | +## Features |
| 6 | +- Pulls metrics from InfluxDB with configurable measurement/field filters |
| 7 | +- Aggregates over a fixed time window (mean/min/max/last) |
| 8 | +- Sends a compact JSON payload to Gemini with optional system instruction |
| 9 | +- Writes the generated summary to an output measurement in the same bucket |
| 10 | +- Can run once (batch mode) or on a fixed schedule |
| 11 | + |
| 12 | +## Requirements |
| 13 | +- Java 21+ (the Docker image uses Temurin 21 JRE but the app targets 17) |
| 14 | +- InfluxDB 2.x with an API token and bucket/org |
| 15 | +- Google Generative Language (Gemini) API key |
| 16 | +- Gradle (wrapper included) |
| 17 | + |
| 18 | +Configuration (Environment Variables) |
| 19 | +The application reads configuration from environment variables at startup. |
| 20 | + |
| 21 | +### Required |
| 22 | +- `INFLUX_URL`: URL of InfluxDB (e.g., http://localhost:8086) |
| 23 | +- `INFLUX_TOKEN`: InfluxDB API token with read/write access to the bucket |
| 24 | +- `INFLUX_ORG`: InfluxDB organization name/ID |
| 25 | +- `INFLUX_BUCKET`: InfluxDB bucket name |
| 26 | +- `GOOGLE_API_KEY`: Google Gemini API key |
| 27 | + |
| 28 | +### Optional (with defaults) |
| 29 | +- `INFLUX_MEASUREMENT_REGEX`: Regex for measurements to include (default: .*) |
| 30 | +- `INFLUX_FIELD_REGEX`: Regex for fields to include (default: unset = all fields) |
| 31 | +- `GOOGLE_MODEL`: Gemini model (default: gemini-2.5-flash) |
| 32 | +- `OUTPUT_MEASUREMENT`: Measurement to write summaries to (default: dashboard_summary) |
| 33 | +- `INTERVAL_MINUTES`: Window size and schedule period in minutes (default: 15) |
| 34 | +- `TIMEZONE`: IANA timezone for scheduling (default: system timezone) |
| 35 | +- `RUN_ONCE`: If true, runs a single cycle and exits (default: false) |
| 36 | +- `SYSTEM_INSTRUCTION`: System prompt sent to Gemini (default: "You are a concise observability assistant.") |
| 37 | + |
| 38 | +## Quick start (local) |
| 39 | +### 1) Export environment variables (example) |
| 40 | + |
| 41 | + |
| 42 | + export INFLUX_URL="http://localhost:8086" |
| 43 | + export INFLUX_TOKEN="<your-token>" |
| 44 | + export INFLUX_ORG="<your-org>" |
| 45 | + export INFLUX_BUCKET="<your-bucket>" |
| 46 | + export GOOGLE_API_KEY="<your-gemini-api-key>" |
| 47 | + |
| 48 | +#### Optional filters and settings |
| 49 | + |
| 50 | + export INFLUX_MEASUREMENT_REGEX="^telemetry_.*$" |
| 51 | + export INFLUX_FIELD_REGEX="^(temperature|humidity)$" |
| 52 | + export INTERVAL_MINUTES=15 |
| 53 | + export RUN_ONCE=false |
| 54 | + |
| 55 | +### 2) Build and run with Gradle |
| 56 | + ./gradlew run |
| 57 | + |
| 58 | + To build a distribution you can run: |
| 59 | + |
| 60 | + ./gradlew installDist |
| 61 | + ./build/install/DashboardSummary/bin/DashboardSummary |
| 62 | + |
| 63 | +## Run once (batch mode) |
| 64 | +Set `RUN_ONCE=true` to execute a single summary cycle and exit. |
| 65 | + |
| 66 | + RUN_ONCE=true ./gradlew run |
| 67 | + # or with the installed distribution |
| 68 | + RUN_ONCE=true ./build/install/DashboardSummary/bin/DashboardSummary |
| 69 | + |
| 70 | +## Docker |
| 71 | +Build the image (multi-stage Dockerfile provided): |
| 72 | + |
| 73 | + docker build -t dashboard-summary:latest . |
| 74 | + |
| 75 | +Run the container (pass env variables): |
| 76 | + |
| 77 | + docker run --rm \ |
| 78 | + -e INFLUX_URL=http://influxdb:8086 \ |
| 79 | + -e INFLUX_TOKEN=YOUR_TOKEN \ |
| 80 | + -e INFLUX_ORG=YOUR_ORG \ |
| 81 | + -e INFLUX_BUCKET=YOUR_BUCKET \ |
| 82 | + -e GOOGLE_API_KEY=YOUR_GEMINI_KEY \ |
| 83 | + -e INFLUX_MEASUREMENT_REGEX=".*" \ |
| 84 | + -e INTERVAL_MINUTES=15 \ |
| 85 | + -e OUTPUT_MEASUREMENT=dashboard_summary \ |
| 86 | + --name dashboard-summary dashboard-summary:latest |
| 87 | + |
| 88 | +## How it works |
| 89 | +- For the last `INTERVAL_MINUTES`, the app queries InfluxDB for each matching measurement/field and computes mean, min, max, and last values. |
| 90 | +- It composes a compact JSON payload with these stats and asks Gemini to write a short summary. |
| 91 | +- The summary is written back to InfluxDB in `OUTPUT_MEASUREMENT` with fields: text (string) and interval_minutes (int), and tag: model. |
| 92 | + |
| 93 | +## Notes and tips |
| 94 | +- Ensure the Influx token has read permission for source measurement(s) and write permission for `OUTPUT_MEASUREMENT` in the target bucket. |
| 95 | +- `TIMEZONE` only affects when periodic runs are scheduled; the data range is relative to "now" per InfluxDB. |
| 96 | +- If you need stricter control over prompting, set `SYSTEM_INSTRUCTION` to guide the model’s tone and focus. |
| 97 | + |
| 98 | +## Troubleshooting |
| 99 | +- Missing configuration: the app logs a clear list of missing variables and exits with code 1. |
| 100 | +- Gemini API errors: you will see the HTTP status and body in logs; verify `GOOGLE_API_KEY` and model. |
| 101 | +- Influx query failures: the app logs a warning per failed query and continues with available data. |
| 102 | + |
| 103 | +## Development |
| 104 | +- Build and test: ./gradlew build |
| 105 | +- Code entry point: com.pathvariable.smartgarden.summary.Main |
| 106 | +- Key classes: Config, GeminiClient, SummaryJob, TimeUtil, MetricKey |
0 commit comments