feat: implement history push mutation and enhanced MCP logging

- Implement pushHistory mutation to support pushing telemetry data to Zabbix trapper items.

- Add VERBOSITY and MCP_LOG_* environment variables for controllable request/response logging in both API and MCP server.

- Enhance ZabbixRESTDataSource with better session handling and error logging.

- Update ZabbixHistory datasource to support history push operations.

- Expand documentation with new cookbook recipes and MCP integration guides.

- Add integration tests for history pushing (src/test/history_push*).

- Reorganize documentation, moving technical product info PDF to docs/use-cases/.

- Update GraphQL generated types and VCR templates.
This commit is contained in:
Andreas Hilbig 2026-02-03 13:29:42 +01:00
parent b646b8c606
commit 7c2dee2b6c
28 changed files with 6036 additions and 3088 deletions

View file

@ -8,12 +8,15 @@ This directory contains practical examples of GraphQL operations for the Zabbix
- [Query All Hosts](./sample_all_hosts_query.graphql): Retrieve basic host information and inventory.
- [Import Hosts](./sample_import_hosts_mutation.graphql): Create or update multiple hosts with tags and group assignments.
- [Query All Devices](./sample_all_devices_query.graphql): Query specialized devices using the `allDevices` query.
- [Tracked Device Query](./sample_tracked_device_query.graphql): Query simulated or tracked devices.
- [Push GeoJSON History](./sample_push_geojson_history.graphql): Push multiple GeoJSON data points to a tracked device.
- [Distance Tracker Test Query](./sample_distance_tracker_test_query.graphql): Comprehensive query for testing specialized `DistanceTrackerDevice` types.
### 📄 Templates
- [Query Templates](./sample_templates_query.graphql): List available templates and their items.
- [Import Templates](./sample_import_templates_mutation.graphql): Create or update complex templates with item definitions and preprocessing.
- [Import Distance Tracker Template](./sample_import_distance_tracker_template.graphql): Example of importing a template for a schema extension.
- [Import Simulated BT Template](./sample_import_simulated_bt_template.graphql): Example of importing a template for a simulated device.
- [Delete Templates](./sample_delete_templates_mutation.graphql): Remove templates by ID or name pattern.
### 📂 Template Groups

View file

@ -0,0 +1,46 @@
### Mutation
Use this mutation to import a template for a simulated device that pushes GeoJSON data via Zabbix Trapper items.
```graphql
mutation ImportSimulatedBTTemplate($templates: [CreateTemplate!]!) {
importTemplates(templates: $templates) {
host
templateid
message
error {
message
}
}
}
```
### Variables
The following sample defines the `SIMULATED_BT_DEVICE` template. Note the `deviceType` tag set to `TrackedDevice`, which instructs the GraphQL API to resolve this host using the specialized `TrackedDevice` type.
We use the `state.current.json_geojson` key for the trapper item. The `json_` prefix ensures that the JSON string received from Zabbix is automatically parsed into a `JSONObject` by the GraphQL resolver.
```json
{
"templates": [
{
"host": "SIMULATED_BT_DEVICE",
"name": "Simulated BT Device",
"groupNames": ["Templates/Roadwork/Devices"],
"tags": [
{ "tag": "class", "value": "roadwork" },
{ "tag": "deviceType", "value": "TrackedDevice" }
],
"items": [
{
"name": "GeoJSON Data",
"type": 2,
"key": "state.current.json_geojson",
"value_type": 4,
"history": "7d",
"description": "Trapper item receiving GeoJSON payloads"
}
]
}
]
}
```

View file

@ -0,0 +1,470 @@
### Mutation
Use this mutation to push multiple GeoJSON data points to a simulated device. Each point is pushed with its own timestamp extracted from the GeoJSON properties.
```graphql
mutation PushGeoJsonHistory($host: String!, $key: String!, $values: [HistoryPushInput!]!) {
pushHistory(host: $host, key: $key, values: $values) {
message
data {
itemid
error {
message
}
}
}
}
```
### Variables
The following variables push 20 GeoJSON features to the `Vehicle1` host.
Note that we use the technical Zabbix key `state.current.json_geojson` (including the `json_` prefix) to target the correct trapper item.
```json
{
"host": "Vehicle1",
"key": "state.current.json_geojson",
"values": [
{
"timestamp": "2026-02-02T16:00:00.000Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:00:00.000Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.980238638943689,
50.94213786322479
]
}
}
},
{
"timestamp": "2026-02-02T16:00:12.838Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:00:12.838Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979929916761165,
50.9418828739594
]
}
}
},
{
"timestamp": "2026-02-02T16:00:24.413Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:00:24.413Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.97947100540884,
50.9418828739594
]
}
}
},
{
"timestamp": "2026-02-02T16:00:38.910Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:00:38.910Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.978962030999412,
50.94205111445655
]
}
}
},
{
"timestamp": "2026-02-02T16:00:48.218Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:00:48.218Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.97871171571623,
50.94222198308785
]
}
}
},
{
"timestamp": "2026-02-02T16:00:55.942Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:00:55.942Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.978469744275316,
50.9423402763876
]
}
}
},
{
"timestamp": "2026-02-02T16:01:07.048Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:01:07.048Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.978269492048469,
50.94209317448525
]
}
}
},
{
"timestamp": "2026-02-02T16:01:18.399Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:01:18.399Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.97871171571623,
50.94214574946821
]
}
}
},
{
"timestamp": "2026-02-02T16:01:27.785Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:01:27.785Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.9789870625279775,
50.942303474059884
]
}
}
},
{
"timestamp": "2026-02-02T16:01:38.408Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:01:38.408Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979103876326803,
50.94255846101797
]
}
}
},
{
"timestamp": "2026-02-02T16:01:50.930Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:01:50.930Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979337503923659,
50.94283447625244
]
}
}
},
{
"timestamp": "2026-02-02T16:01:58.600Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:01:58.600Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979475177329533,
50.94300534200477
]
}
}
},
{
"timestamp": "2026-02-02T16:02:15.429Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:02:15.429Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979212346282509,
50.942618921637944
]
}
}
},
{
"timestamp": "2026-02-02T16:02:30.260Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:02:30.260Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.97896620292093,
50.94228244414538
]
}
}
},
{
"timestamp": "2026-02-02T16:02:36.242Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:02:36.242Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.978816013750361,
50.942166779444534
]
}
}
},
{
"timestamp": "2026-02-02T16:02:46.091Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:02:46.091Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.978582386152624,
50.94196962304159
]
}
}
},
{
"timestamp": "2026-02-02T16:02:56.752Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:02:56.752Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979003750213366,
50.941948592976075
]
}
}
},
{
"timestamp": "2026-02-02T16:03:15.630Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:03:15.630Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.979721320691965,
50.94181452608393
]
}
}
},
{
"timestamp": "2026-02-02T16:03:24.823Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:03:24.823Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.980071762088585,
50.9418776164344
]
}
}
},
{
"timestamp": "2026-02-02T16:03:36.019Z",
"value": {
"type": "Feature",
"properties": {
"time": "2026-02-02T16:03:36.019Z",
"deviceType": "locationTracker",
"parent": {
"type": "vehicle",
"subType": "forklift",
"name": "vehicle1"
}
},
"geometry": {
"type": "Point",
"coordinates": [
6.980234467022115,
50.94213786322479
]
}
}
}
]
}
```

View file

@ -0,0 +1,19 @@
### Query
Retrieve the state of tracked devices.
```graphql
query GetSimulatedState {
allDevices(tag_deviceType: ["TrackedDevice"]) {
name
host
deviceType
... on TrackedDevice {
state {
current {
geojson
}
}
}
}
}
```