Compare commits
10 Commits
d95723f540
...
4e6a75c93d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e6a75c93d | ||
|
|
ffe5c44960 | ||
|
|
c1dec23e3c | ||
|
|
a2f8b6433a | ||
|
|
7eb80d3f23 | ||
|
|
2b5bfd4de6 | ||
|
|
5be89db773 | ||
|
|
0316e42c8b | ||
|
|
28c32d4dbf | ||
|
|
3ea69e2f8e |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Fix support of applicationids filters with Zabbix problems for versions older than 5.0.x
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Fix when to fetch Zabbix version before issuing new requests
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Support adding custom values in dropdowns for all query types
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Add support for host tags when querying metrics
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Add support for disabled items in Item variable type
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Standardization across Zabbix UI components
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': patch
|
||||
---
|
||||
|
||||
Upgrade react-table to v8
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Moves health check to the backend
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': major
|
||||
---
|
||||
|
||||
Migrates use of DatasourceApi to DatasourceWithBackend
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'grafana-zabbix': minor
|
||||
---
|
||||
|
||||
Fix how frontend and backend querying responses are merged
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG grafana_version=latest
|
||||
ARG grafana_version=latest@sha256:703b4a3aff457041dcbd15bf36dbc8bb83cb513b72b0912056985712be4c01bd
|
||||
ARG grafana_image=grafana-enterprise
|
||||
|
||||
FROM grafana/${grafana_image}:${grafana_version}
|
||||
|
||||
2
.github/workflows/publish.yaml
vendored
2
.github/workflows/publish.yaml
vendored
@@ -27,7 +27,7 @@ on:
|
||||
jobs:
|
||||
cd:
|
||||
name: CD
|
||||
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@ci-cd-workflows/v4.3.0
|
||||
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@ci-cd-workflows/v5.1.0
|
||||
with:
|
||||
golangci-lint-version: '2.7.2'
|
||||
go-version: '1.25.5'
|
||||
|
||||
2
.github/workflows/push.yaml
vendored
2
.github/workflows/push.yaml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
jobs:
|
||||
ci:
|
||||
name: CI
|
||||
uses: grafana/plugin-ci-workflows/.github/workflows/ci.yml@ci-cd-workflows/v4.3.0
|
||||
uses: grafana/plugin-ci-workflows/.github/workflows/ci.yml@ci-cd-workflows/v5.1.0
|
||||
with:
|
||||
go-version: '1.25.5'
|
||||
golangci-lint-version: '2.7.2'
|
||||
|
||||
22
CHANGELOG.md
22
CHANGELOG.md
@@ -1,5 +1,27 @@
|
||||
# Change Log
|
||||
|
||||
## 6.1.0
|
||||
|
||||
🎉 Migrates use of DatasourceApi to DatasourceWithBackend
|
||||
|
||||
🚀 Fix support of `applicationids` filters with Zabbix problems for versions older than 5.0.x
|
||||
|
||||
🚀 Fix when to fetch Zabbix version before issuing new requests
|
||||
|
||||
🚀 Support adding custom values in dropdowns for all query types
|
||||
|
||||
🚀 Add support for host tags when querying metrics
|
||||
|
||||
🚀 Add support for disabled items in Item variable type
|
||||
|
||||
🚀 Standardization across Zabbix UI components
|
||||
|
||||
🚀 Moves health check to the backend
|
||||
|
||||
🚀 Fix how frontend and backend querying responses are merged
|
||||
|
||||
🐛 Upgrade react-table to v8
|
||||
|
||||
## 6.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"ignoreRegExpList": ["import\\s*\\((.|[\r\n])*?\\)", "import\\s*.*\".*?\"", "\\[@.+\\]"],
|
||||
"words": [
|
||||
"alexanderzobnin",
|
||||
"applicationids",
|
||||
"datapoint",
|
||||
"datapoints",
|
||||
"datasource",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3
|
||||
FROM python:3@sha256:6d58c1a9444bc2664f0fa20c43a592fcdb2698eb9a9c32257516538a2746c19a
|
||||
|
||||
ENV ZBX_API_URL=http://zabbix-web
|
||||
ENV ZBX_API_USER="Admin"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
ssl-cert:
|
||||
image: alpine:latest
|
||||
image: alpine:latest@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
|
||||
command: |
|
||||
sh -c "if [ ! -f /certs/nginx.crt ] || [ ! -f /certs/nginx.key ]; then
|
||||
apk add --no-cache openssl &&
|
||||
@@ -26,7 +26,7 @@ services:
|
||||
|
||||
# Zabbix
|
||||
zabbix-server:
|
||||
image: zabbix/zabbix-server-pgsql:alpine-5.0-latest
|
||||
image: zabbix/zabbix-server-pgsql:alpine-5.0-latest@sha256:b88c636ec3298529358914aa7fd04d3f7ae3da0eab261b405cb2a9fcb4fa5eae
|
||||
ports:
|
||||
- '10051:10051'
|
||||
depends_on:
|
||||
@@ -39,7 +39,7 @@ services:
|
||||
POSTGRES_DB: zabbix
|
||||
|
||||
zabbix-web:
|
||||
image: zabbix/zabbix-web-nginx-pgsql:alpine-5.0-latest
|
||||
image: zabbix/zabbix-web-nginx-pgsql:alpine-5.0-latest@sha256:90d9d85d42d46a4978091bd6deb405e6c8486fd53af5720a6f7a6135e6baaa4b
|
||||
ports:
|
||||
- '443:443'
|
||||
- '8188:8080'
|
||||
@@ -65,7 +65,7 @@ services:
|
||||
- ../nginx/.htpasswd:/etc/nginx/.htpasswd:ro
|
||||
|
||||
database:
|
||||
image: postgres:14
|
||||
image: postgres:18@sha256:bfe50b2b0ddd9b55eadedd066fe24c7c6fe06626185b73358c480ea37868024d
|
||||
ports:
|
||||
- '15432:5432'
|
||||
environment:
|
||||
@@ -73,13 +73,13 @@ services:
|
||||
POSTGRES_PASSWORD: zabbix
|
||||
|
||||
zabbix-agent:
|
||||
image: zabbix/zabbix-agent:alpine-5.0-latest
|
||||
image: zabbix/zabbix-agent:alpine-5.0-latest@sha256:c34ca68c3120b1918bceb394f2275f6aa67ddecce641a0033fdea5c84b89731d
|
||||
environment:
|
||||
ZBX_SERVER_HOST: zabbix-server
|
||||
ZBX_SERVER_PORT: 10051
|
||||
|
||||
zabbix-proxy:
|
||||
image: zabbix/zabbix-proxy-sqlite3:alpine-5.0-latest
|
||||
image: zabbix/zabbix-proxy-sqlite3:alpine-5.0-latest@sha256:a963b30b2e4352be890c93f599749d42a8e6a8e549629ccc6b30de437ecd4a5f
|
||||
environment:
|
||||
ZBX_PROXYMODE: 0
|
||||
ZBX_HOSTNAME: zabbix-proxy
|
||||
@@ -87,7 +87,7 @@ services:
|
||||
ZBX_SERVER_PORT: 10051
|
||||
|
||||
zabbix-agent-proxy:
|
||||
image: zabbix/zabbix-agent:alpine-5.0-latest
|
||||
image: zabbix/zabbix-agent:alpine-5.0-latest@sha256:c34ca68c3120b1918bceb394f2275f6aa67ddecce641a0033fdea5c84b89731d
|
||||
environment:
|
||||
ZBX_SERVER_HOST: zabbix-proxy
|
||||
ZBX_SERVER_PORT: 10051
|
||||
@@ -117,7 +117,7 @@ services:
|
||||
|
||||
# backend
|
||||
redis_backend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_backend_01:
|
||||
build: ../zas-agent
|
||||
@@ -135,7 +135,7 @@ services:
|
||||
|
||||
# frontend
|
||||
redis_frontend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_frontend_01:
|
||||
build: ../zas-agent
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:2.7
|
||||
FROM python:2.7@sha256:cfa62318c459b1fde9e0841c619906d15ada5910d625176e24bf692cf8a2601d
|
||||
|
||||
ENV ZBX_API_URL=http://zabbix-web:8080
|
||||
ENV ZBX_API_USER="Admin"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
ssl-cert:
|
||||
image: alpine:latest
|
||||
image: alpine:latest@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
|
||||
command: |
|
||||
sh -c "if [ ! -f /certs/nginx.crt ] || [ ! -f /certs/nginx.key ]; then
|
||||
apk add --no-cache openssl &&
|
||||
@@ -26,7 +26,7 @@ services:
|
||||
|
||||
# Zabbix
|
||||
zabbix-server:
|
||||
image: zabbix/zabbix-server-pgsql:alpine-6.0-latest
|
||||
image: zabbix/zabbix-server-pgsql:alpine-6.0-latest@sha256:dbc5a2a27b1163f450b86d5633a8a878c67fb895d435d49fb0f2f6461e43138f
|
||||
ports:
|
||||
- '10051:10051'
|
||||
depends_on:
|
||||
@@ -43,7 +43,7 @@ services:
|
||||
ZBX_DEBUGLEVEL: 3
|
||||
|
||||
zabbix-web:
|
||||
image: zabbix/zabbix-web-nginx-pgsql:alpine-6.0-latest
|
||||
image: zabbix/zabbix-web-nginx-pgsql:alpine-6.0-latest@sha256:e034dd99e711ebb3c28ae87750b818279b857504cdac9be521743ecfbc9711e0
|
||||
ports:
|
||||
- '443:443'
|
||||
- '8188:8080'
|
||||
@@ -64,7 +64,7 @@ services:
|
||||
POSTGRES_DB: zabbix
|
||||
|
||||
database:
|
||||
image: postgres:15
|
||||
image: postgres:18@sha256:bfe50b2b0ddd9b55eadedd066fe24c7c6fe06626185b73358c480ea37868024d
|
||||
ports:
|
||||
- '15432:5432'
|
||||
command: postgres -c 'max_connections=1000'
|
||||
@@ -73,7 +73,7 @@ services:
|
||||
POSTGRES_PASSWORD: zabbix
|
||||
|
||||
zabbix-agent:
|
||||
image: zabbix/zabbix-agent:alpine-6.0-latest
|
||||
image: zabbix/zabbix-agent:alpine-6.0-latest@sha256:9eab77e4f23e68746f935ab71f3c828a6bfc73b2e2783c5453d61a24f996bb6b
|
||||
environment:
|
||||
ZBX_SERVER_HOST: zabbix-server
|
||||
ZBX_SERVER_PORT: 10051
|
||||
@@ -99,7 +99,7 @@ services:
|
||||
|
||||
# backend
|
||||
redis_backend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_backend_01:
|
||||
build: ../zas-agent
|
||||
@@ -118,7 +118,7 @@ services:
|
||||
|
||||
# frontend
|
||||
redis_frontend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_frontend_01:
|
||||
build: ../zas-agent
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.12-slim-bullseye
|
||||
FROM python:3.12-slim-bullseye@sha256:411fa4dcfdce7e7a3057c45662beba9dcd4fa36b2e50a2bfcd6c9333e59bf0db
|
||||
|
||||
ENV ZBX_API_URL=http://zabbix-web:8080
|
||||
ENV ZBX_API_USER="Admin"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
ssl-cert:
|
||||
image: alpine:latest
|
||||
image: alpine:latest@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
|
||||
command: |
|
||||
sh -c "if [ ! -f /certs/nginx.crt ] || [ ! -f /certs/nginx.key ]; then
|
||||
apk add --no-cache openssl &&
|
||||
@@ -26,7 +26,7 @@ services:
|
||||
|
||||
# Zabbix
|
||||
zabbix-server:
|
||||
image: zabbix/zabbix-server-pgsql:alpine-7.0-latest
|
||||
image: zabbix/zabbix-server-pgsql:alpine-7.0-latest@sha256:b3c1451adf27e28741fe3b2b3b614c52b0ac68f749b2515224536ef2c1474473
|
||||
ports:
|
||||
- '10051:10051'
|
||||
depends_on:
|
||||
@@ -43,7 +43,7 @@ services:
|
||||
ZBX_DEBUGLEVEL: 3
|
||||
|
||||
zabbix-web:
|
||||
image: zabbix/zabbix-web-nginx-pgsql:alpine-7.0-latest
|
||||
image: zabbix/zabbix-web-nginx-pgsql:alpine-7.0-latest@sha256:08b2b13e1c92f8cdce81238cdbbb89d1fbc5863e5e7ba0310406212d87988d53
|
||||
ports:
|
||||
- '443:443'
|
||||
- '8188:8080'
|
||||
@@ -64,7 +64,7 @@ services:
|
||||
POSTGRES_DB: zabbix
|
||||
|
||||
database:
|
||||
image: postgres:16
|
||||
image: postgres:18@sha256:bfe50b2b0ddd9b55eadedd066fe24c7c6fe06626185b73358c480ea37868024d
|
||||
ports:
|
||||
- '15432:5432'
|
||||
command: postgres -c 'max_connections=1000'
|
||||
@@ -73,7 +73,7 @@ services:
|
||||
POSTGRES_PASSWORD: zabbix
|
||||
|
||||
zabbix-agent:
|
||||
image: zabbix/zabbix-agent:alpine-7.0-latest
|
||||
image: zabbix/zabbix-agent:alpine-7.0-latest@sha256:71f1f22b3828f47b714a1bbef39b456453e0e552461d138f36e18a35732302ba
|
||||
environment:
|
||||
ZBX_SERVER_HOST: zabbix-server
|
||||
ZBX_SERVER_PORT: 10051
|
||||
@@ -99,7 +99,7 @@ services:
|
||||
|
||||
# backend
|
||||
redis_backend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_backend_01:
|
||||
build: ../zas-agent
|
||||
@@ -118,7 +118,7 @@ services:
|
||||
|
||||
# frontend
|
||||
redis_frontend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_frontend_01:
|
||||
build: ../zas-agent
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.12-slim-bullseye
|
||||
FROM python:3.12-slim-bullseye@sha256:411fa4dcfdce7e7a3057c45662beba9dcd4fa36b2e50a2bfcd6c9333e59bf0db
|
||||
|
||||
ENV ZBX_API_URL=http://zabbix-web:8080
|
||||
ENV ZBX_API_USER="Admin"
|
||||
|
||||
@@ -12,7 +12,7 @@ services:
|
||||
|
||||
# Zabbix
|
||||
zabbix-server:
|
||||
image: zabbix/zabbix-server-pgsql:alpine-7.2-latest
|
||||
image: zabbix/zabbix-server-pgsql:alpine-7.2-latest@sha256:5c1aeceb24d6a07b64667a97d42053e3421c207aec39aca86d87980a30b01f5b
|
||||
ports:
|
||||
- '10051:10051'
|
||||
depends_on:
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
ZBX_DEBUGLEVEL: 3
|
||||
|
||||
zabbix-web:
|
||||
image: zabbix/zabbix-web-apache-pgsql:alpine-7.2-latest
|
||||
image: zabbix/zabbix-web-apache-pgsql:alpine-7.2-latest@sha256:70a301e5c25b9db11bde09ec5b1ba5c25480c3c63e70f01d51534d9648627ff6
|
||||
ports:
|
||||
- '8188:8080'
|
||||
depends_on:
|
||||
@@ -45,7 +45,7 @@ services:
|
||||
POSTGRES_DB: zabbix
|
||||
|
||||
database:
|
||||
image: postgres:16
|
||||
image: postgres:18@sha256:bfe50b2b0ddd9b55eadedd066fe24c7c6fe06626185b73358c480ea37868024d
|
||||
ports:
|
||||
- '15432:5432'
|
||||
command: postgres -c 'max_connections=1000'
|
||||
@@ -54,7 +54,7 @@ services:
|
||||
POSTGRES_PASSWORD: zabbix
|
||||
|
||||
zabbix-agent:
|
||||
image: zabbix/zabbix-agent:alpine-7.2-latest
|
||||
image: zabbix/zabbix-agent:alpine-7.2-latest@sha256:0bb96e2afe24c71dcd38e16f9dff6e56b4aebadff5267ce354b39a79f4a07255
|
||||
environment:
|
||||
ZBX_SERVER_HOST: zabbix-server
|
||||
ZBX_SERVER_PORT: 10051
|
||||
@@ -80,7 +80,7 @@ services:
|
||||
|
||||
# backend
|
||||
redis_backend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_backend_01:
|
||||
build: ../zas-agent
|
||||
@@ -99,7 +99,7 @@ services:
|
||||
|
||||
# frontend
|
||||
redis_frontend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_frontend_01:
|
||||
build: ../zas-agent
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.13-slim-bookworm
|
||||
FROM python:3.13-slim-bookworm@sha256:0c5171fd1e80d3133604e1006aa5f788c5f020631537dd1e09edcbe874bb8192
|
||||
|
||||
ENV ZBX_API_URL=http://zabbix-web:8080
|
||||
ENV ZBX_API_USER="Admin"
|
||||
|
||||
@@ -12,7 +12,7 @@ services:
|
||||
|
||||
# Zabbix
|
||||
zabbix-server:
|
||||
image: zabbix/zabbix-server-pgsql:alpine-7.4-latest
|
||||
image: zabbix/zabbix-server-pgsql:alpine-7.4-latest@sha256:a6f748d96bfa4d361df5e9284eba041c475e7ff26c1358f8f189969437ebdb9b
|
||||
ports:
|
||||
- '10051:10051'
|
||||
depends_on:
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
ZBX_DEBUGLEVEL: 3
|
||||
|
||||
zabbix-web:
|
||||
image: zabbix/zabbix-web-apache-pgsql:alpine-7.4-latest
|
||||
image: zabbix/zabbix-web-apache-pgsql:alpine-7.4-latest@sha256:9b5ad53c684c9f5d7b15c626e22e3d2c97c2b0b2b05ce811d1a8fe42416cd01b
|
||||
ports:
|
||||
- '8188:8080'
|
||||
depends_on:
|
||||
@@ -45,7 +45,7 @@ services:
|
||||
POSTGRES_DB: zabbix
|
||||
|
||||
database:
|
||||
image: postgres:16
|
||||
image: postgres:18@sha256:bfe50b2b0ddd9b55eadedd066fe24c7c6fe06626185b73358c480ea37868024d
|
||||
ports:
|
||||
- '15432:5432'
|
||||
command: postgres -c 'max_connections=1000'
|
||||
@@ -54,7 +54,7 @@ services:
|
||||
POSTGRES_PASSWORD: zabbix
|
||||
|
||||
zabbix-agent:
|
||||
image: zabbix/zabbix-agent:alpine-7.4-latest
|
||||
image: zabbix/zabbix-agent:alpine-7.4-latest@sha256:2a5989f552e70c1a7d48870ff6002ebbcda1a907e42046851aeae9feba614ac4
|
||||
environment:
|
||||
ZBX_SERVER_HOST: zabbix-server
|
||||
ZBX_SERVER_PORT: 10051
|
||||
@@ -80,7 +80,7 @@ services:
|
||||
|
||||
# backend
|
||||
redis_backend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_backend_01:
|
||||
build: ../zas-agent
|
||||
@@ -99,7 +99,7 @@ services:
|
||||
|
||||
# frontend
|
||||
redis_frontend:
|
||||
image: redis:alpine
|
||||
image: redis:alpine@sha256:6cbef353e480a8a6e7f10ec545f13d7d3fa85a212cdcc5ffaf5a1c818b9d3798
|
||||
|
||||
zas_frontend_01:
|
||||
build: ../zas-agent
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:2.7
|
||||
FROM python:2.7@sha256:cfa62318c459b1fde9e0841c619906d15ada5910d625176e24bf692cf8a2601d
|
||||
|
||||
# ENV ZAS_SOURCE_URL=https://github.com/vulogov/zas_agent/archive/master.zip
|
||||
# ENV ZAS_ARC_NAME=zas_agent-master
|
||||
|
||||
14
go.mod
14
go.mod
@@ -15,7 +15,7 @@ require (
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/net v0.48.0
|
||||
gotest.tools v2.2.0+incompatible
|
||||
)
|
||||
|
||||
@@ -87,12 +87,12 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 // indirect
|
||||
golang.org/x/mod v0.28.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
|
||||
|
||||
28
go.sum
28
go.sum
@@ -235,19 +235,19 @@ golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 h1:TQwNpfvNkxAVlItJf6Cr5JTsV
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -260,20 +260,20 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo=
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "grafana-zabbix",
|
||||
"version": "6.0.3",
|
||||
"version": "6.1.0",
|
||||
"description": "Zabbix plugin for Grafana",
|
||||
"homepage": "http://grafana-zabbix.org",
|
||||
"bugs": {
|
||||
@@ -54,13 +54,13 @@
|
||||
"@swc/helpers": "0.5.18",
|
||||
"@swc/jest": "0.2.39",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
"@testing-library/dom": "10.4.1",
|
||||
"@testing-library/jest-dom": "6.9.1",
|
||||
"@testing-library/react": "16.3.1",
|
||||
"@types/grafana": "github:CorpGlory/types-grafana",
|
||||
"@types/jest": "30.0.0",
|
||||
"@types/lodash": "4.17.21",
|
||||
"@types/node": "25.0.3",
|
||||
"@types/lodash": "4.17.22",
|
||||
"@types/node": "25.0.5",
|
||||
"@types/react": "18.3.27",
|
||||
"@types/react-dom": "18.3.7",
|
||||
"@typescript-eslint/eslint-plugin": "8.52.0",
|
||||
@@ -71,7 +71,7 @@
|
||||
"css-loader": "7.1.2",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-jsdoc": "61.5.0",
|
||||
"eslint-plugin-jsdoc": "62.0.0",
|
||||
"eslint-plugin-prettier": "5.5.4",
|
||||
"eslint-plugin-react": "7.37.5",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
|
||||
@@ -4,16 +4,20 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/httpclient"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/metrics"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/settings"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbixapi"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -113,6 +117,11 @@ func (ds *ZabbixDatasource) QueryData(ctx context.Context, req *backend.QueryDat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queryTimeout := zabbixDS.Settings.QueryTimeout
|
||||
if queryTimeout <= 0 {
|
||||
queryTimeout = 60 * time.Second // Default to 60 seconds if not configured
|
||||
}
|
||||
|
||||
for _, q := range req.Queries {
|
||||
res := backend.DataResponse{}
|
||||
query, err := ReadQuery(q)
|
||||
@@ -122,22 +131,52 @@ func (ds *ZabbixDatasource) QueryData(ctx context.Context, req *backend.QueryDat
|
||||
} else if err := ValidateTimeRange(query.TimeRange); err != nil {
|
||||
// Validate time range before processing any query
|
||||
res = backend.ErrorResponseWithErrorSource(err)
|
||||
} else if query.QueryType == MODE_METRICS {
|
||||
frames, err := zabbixDS.queryNumericItems(ctx, &query)
|
||||
if err != nil {
|
||||
res = backend.ErrorResponseWithErrorSource(err)
|
||||
} else {
|
||||
// Create a context with timeout for this specific query
|
||||
queryCtx, cancel := context.WithTimeout(ctx, queryTimeout)
|
||||
|
||||
// Execute query with timeout context in an anonymous function to ensure cancel is called after each iteration
|
||||
func() {
|
||||
defer cancel()
|
||||
|
||||
var frames []*data.Frame
|
||||
var queryErr error
|
||||
|
||||
switch query.QueryType {
|
||||
case MODE_METRICS:
|
||||
frames, queryErr = zabbixDS.queryNumericItems(queryCtx, &query)
|
||||
case MODE_ITEMID:
|
||||
frames, queryErr = zabbixDS.queryItemIdData(queryCtx, &query)
|
||||
default:
|
||||
queryErr = backend.DownstreamError(ErrNonMetricQueryNotSupported)
|
||||
}
|
||||
|
||||
// Check if query timed out
|
||||
if queryErr != nil {
|
||||
if errors.Is(queryCtx.Err(), context.DeadlineExceeded) {
|
||||
// Query exceeded the configured timeout
|
||||
timeoutMsg := fmt.Sprintf(
|
||||
"Query execution exceeded maximum allowed time (%v). Query was automatically terminated to prevent excessive resource consumption.",
|
||||
queryTimeout,
|
||||
)
|
||||
ds.logger.Warn(
|
||||
"Query timeout exceeded",
|
||||
"refId", q.RefID,
|
||||
"queryType", query.QueryType,
|
||||
"timeout", queryTimeout,
|
||||
"datasourceId", req.PluginContext.DataSourceInstanceSettings.ID,
|
||||
)
|
||||
res = backend.ErrorResponseWithErrorSource(
|
||||
backend.DownstreamError(fmt.Errorf("query timeout: %s", timeoutMsg)),
|
||||
)
|
||||
res.Status = http.StatusRequestTimeout
|
||||
} else {
|
||||
res = backend.ErrorResponseWithErrorSource(queryErr)
|
||||
}
|
||||
} else {
|
||||
res.Frames = append(res.Frames, frames...)
|
||||
}
|
||||
} else if query.QueryType == MODE_ITEMID {
|
||||
frames, err := zabbixDS.queryItemIdData(ctx, &query)
|
||||
if err != nil {
|
||||
res = backend.ErrorResponseWithErrorSource(err)
|
||||
} else {
|
||||
res.Frames = append(res.Frames, frames...)
|
||||
}
|
||||
} else {
|
||||
res = backend.ErrorResponseWithErrorSource(backend.DownstreamError(ErrNonMetricQueryNotSupported))
|
||||
}()
|
||||
}
|
||||
qdr.Responses[q.RefID] = res
|
||||
}
|
||||
|
||||
@@ -2,8 +2,12 @@ package datasource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/settings"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
@@ -66,3 +70,101 @@ func TestZabbixBackend_getCachedDatasource(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryData_QueryTimeoutConfiguration(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
queryTimeout interface{}
|
||||
expectedTimeout time.Duration
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "Default timeout when not configured",
|
||||
queryTimeout: nil,
|
||||
expectedTimeout: 60 * time.Second,
|
||||
description: "Should use default 60 seconds when queryTimeout is not set",
|
||||
},
|
||||
{
|
||||
name: "Default timeout when zero",
|
||||
queryTimeout: 0,
|
||||
expectedTimeout: 60 * time.Second,
|
||||
description: "Should use default 60 seconds when queryTimeout is 0",
|
||||
},
|
||||
{
|
||||
name: "Custom timeout configured",
|
||||
queryTimeout: 30,
|
||||
expectedTimeout: 30 * time.Second,
|
||||
description: "Should use configured queryTimeout value",
|
||||
},
|
||||
{
|
||||
name: "Custom timeout as string",
|
||||
queryTimeout: "45",
|
||||
expectedTimeout: 45 * time.Second,
|
||||
description: "Should parse string queryTimeout value",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Create datasource settings with queryTimeout
|
||||
jsonData := map[string]interface{}{
|
||||
"queryTimeout": tt.queryTimeout,
|
||||
}
|
||||
jsonBytes, _ := json.Marshal(jsonData)
|
||||
|
||||
dsSettings := backend.DataSourceInstanceSettings{
|
||||
ID: 1,
|
||||
Name: "TestDatasource",
|
||||
URL: "http://zabbix.org/zabbix",
|
||||
JSONData: jsonBytes,
|
||||
}
|
||||
|
||||
// Parse settings to verify timeout is set correctly
|
||||
zabbixSettings, err := settings.ReadZabbixSettings(&dsSettings)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, tt.expectedTimeout, zabbixSettings.QueryTimeout, tt.description)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryData_QueryTimeoutContextCreation(t *testing.T) {
|
||||
// Test that query timeout context is properly created with the configured timeout
|
||||
jsonData := map[string]interface{}{
|
||||
"queryTimeout": 5, // 5 seconds
|
||||
}
|
||||
jsonBytes, _ := json.Marshal(jsonData)
|
||||
|
||||
dsSettings := backend.DataSourceInstanceSettings{
|
||||
ID: 1,
|
||||
Name: "TestDatasource",
|
||||
URL: "http://zabbix.org/zabbix",
|
||||
JSONData: jsonBytes,
|
||||
}
|
||||
|
||||
// Verify queryTimeout is set correctly
|
||||
zabbixSettings, err := settings.ReadZabbixSettings(&dsSettings)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 5*time.Second, zabbixSettings.QueryTimeout)
|
||||
|
||||
// Test that context with timeout is created correctly
|
||||
ctx := context.Background()
|
||||
queryCtx, cancel := context.WithTimeout(ctx, zabbixSettings.QueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
// Verify context has deadline set
|
||||
deadline, ok := queryCtx.Deadline()
|
||||
assert.Assert(t, ok, "Context should have a deadline")
|
||||
assert.Assert(t, deadline.After(time.Now()), "Deadline should be in the future")
|
||||
assert.Assert(t, deadline.Before(time.Now().Add(6*time.Second)), "Deadline should be approximately 5 seconds from now")
|
||||
}
|
||||
|
||||
func TestQueryData_QueryTimeoutErrorMessage(t *testing.T) {
|
||||
// Test that timeout error message contains the expected information
|
||||
timeoutMsg := "Query execution exceeded maximum allowed time (5s). Query was automatically terminated to prevent excessive resource consumption."
|
||||
|
||||
// Verify error message format
|
||||
assert.Assert(t, strings.Contains(timeoutMsg, "Query execution exceeded maximum allowed time"))
|
||||
assert.Assert(t, strings.Contains(timeoutMsg, "5s"))
|
||||
assert.Assert(t, strings.Contains(timeoutMsg, "automatically terminated"))
|
||||
assert.Assert(t, strings.Contains(timeoutMsg, "prevent excessive resource consumption"))
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/timeseries"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
@@ -14,7 +14,13 @@ type ZabbixDatasourceSettingsDTO struct {
|
||||
TrendsFrom string `json:"trendsFrom"`
|
||||
TrendsRange string `json:"trendsRange"`
|
||||
CacheTTL string `json:"cacheTTL"`
|
||||
// Timeout is the HTTP client connection timeout in seconds for individual API requests to Zabbix.
|
||||
// This controls how long to wait for a single HTTP request/response cycle. Default is 30 seconds.
|
||||
Timeout interface{} `json:"timeout"`
|
||||
// QueryTimeout is the maximum execution time in seconds for entire database queries initiated by the plugin.
|
||||
// This controls the total time allowed for a complete query execution (which may involve multiple API calls).
|
||||
// Queries exceeding this limit will be automatically terminated. Default is 60 seconds.
|
||||
QueryTimeout interface{} `json:"queryTimeout"`
|
||||
|
||||
DisableDataAlignment bool `json:"disableDataAlignment"`
|
||||
DisableReadOnlyUsersAck bool `json:"disableReadOnlyUsersAck"`
|
||||
@@ -27,7 +33,13 @@ type ZabbixDatasourceSettings struct {
|
||||
TrendsFrom time.Duration
|
||||
TrendsRange time.Duration
|
||||
CacheTTL time.Duration
|
||||
// Timeout is the HTTP client connection timeout for individual API requests to Zabbix.
|
||||
// This controls how long to wait for a single HTTP request/response cycle. Default is 30 seconds.
|
||||
Timeout time.Duration
|
||||
// QueryTimeout is the maximum execution time for entire database queries initiated by the plugin.
|
||||
// This controls the total time allowed for a complete query execution (which may involve multiple API calls).
|
||||
// Queries exceeding this limit will be automatically terminated. Default is 60 seconds.
|
||||
QueryTimeout time.Duration
|
||||
|
||||
DisableDataAlignment bool `json:"disableDataAlignment"`
|
||||
DisableReadOnlyUsersAck bool `json:"disableReadOnlyUsersAck"`
|
||||
|
||||
@@ -11,6 +11,31 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
)
|
||||
|
||||
// parseTimeoutValue parses a timeout value from various types (string, float64, int64, int)
|
||||
// and returns it as int64. If the value is empty or invalid, it returns the default value.
|
||||
// The fieldName parameter is used for error messages.
|
||||
func parseTimeoutValue(value interface{}, defaultValue int64, fieldName string) (int64, error) {
|
||||
switch t := value.(type) {
|
||||
case string:
|
||||
if t == "" {
|
||||
return defaultValue, nil
|
||||
}
|
||||
timeoutInt, err := strconv.Atoi(t)
|
||||
if err != nil {
|
||||
return 0, errors.New("failed to parse " + fieldName + ": " + err.Error())
|
||||
}
|
||||
return int64(timeoutInt), nil
|
||||
case float64:
|
||||
return int64(t), nil
|
||||
case int64:
|
||||
return t, nil
|
||||
case int:
|
||||
return int64(t), nil
|
||||
default:
|
||||
return defaultValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings) (*ZabbixDatasourceSettings, error) {
|
||||
zabbixSettingsDTO := &ZabbixDatasourceSettingsDTO{}
|
||||
|
||||
@@ -33,10 +58,6 @@ func ReadZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings)
|
||||
zabbixSettingsDTO.CacheTTL = "1h"
|
||||
}
|
||||
|
||||
//if zabbixSettingsDTO.Timeout == 0 {
|
||||
// zabbixSettingsDTO.Timeout = 30
|
||||
//}
|
||||
|
||||
trendsFrom, err := gtime.ParseInterval(zabbixSettingsDTO.TrendsFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -52,22 +73,19 @@ func ReadZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var timeout int64
|
||||
switch t := zabbixSettingsDTO.Timeout.(type) {
|
||||
case string:
|
||||
if t == "" {
|
||||
timeout = 30
|
||||
break
|
||||
}
|
||||
timeoutInt, err := strconv.Atoi(t)
|
||||
timeout, err := parseTimeoutValue(zabbixSettingsDTO.Timeout, 30, "timeout")
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to parse timeout: " + err.Error())
|
||||
return nil, err
|
||||
}
|
||||
timeout = int64(timeoutInt)
|
||||
case float64:
|
||||
timeout = int64(t)
|
||||
default:
|
||||
timeout = 30
|
||||
|
||||
queryTimeout, err := parseTimeoutValue(zabbixSettingsDTO.QueryTimeout, 60, "queryTimeout")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Default to 60 seconds if queryTimeout is 0 or negative
|
||||
if queryTimeout <= 0 {
|
||||
queryTimeout = 60
|
||||
}
|
||||
|
||||
zabbixSettings := &ZabbixDatasourceSettings{
|
||||
@@ -77,6 +95,7 @@ func ReadZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings)
|
||||
TrendsRange: trendsRange,
|
||||
CacheTTL: cacheTTL,
|
||||
Timeout: time.Duration(timeout) * time.Second,
|
||||
QueryTimeout: time.Duration(queryTimeout) * time.Second,
|
||||
DisableDataAlignment: zabbixSettingsDTO.DisableDataAlignment,
|
||||
DisableReadOnlyUsersAck: zabbixSettingsDTO.DisableReadOnlyUsersAck,
|
||||
}
|
||||
|
||||
104
pkg/settings/settings_test.go
Normal file
104
pkg/settings/settings_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseTimeoutValue(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
defaultValue int64
|
||||
fieldName string
|
||||
want int64
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid string",
|
||||
value: "45",
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 45,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty string returns default",
|
||||
value: "",
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 30,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid string returns error",
|
||||
value: "not-a-number",
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 0,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "float64 value",
|
||||
value: float64(60),
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 60,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "int64 value",
|
||||
value: int64(90),
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 90,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "int value",
|
||||
value: int(120),
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 120,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "nil returns default",
|
||||
value: nil,
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 30,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "unknown type returns default",
|
||||
value: []string{"invalid"},
|
||||
defaultValue: 60,
|
||||
fieldName: "queryTimeout",
|
||||
want: 60,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "zero string value",
|
||||
value: "0",
|
||||
defaultValue: 30,
|
||||
fieldName: "timeout",
|
||||
want: 0,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parseTimeoutValue(tt.value, tt.defaultValue, tt.fieldName)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.fieldName)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,7 @@ export const ConfigEditor = (props: Props) => {
|
||||
trendsRange: '',
|
||||
cacheTTL: '',
|
||||
timeout: undefined,
|
||||
queryTimeout: undefined,
|
||||
disableDataAlignment: false,
|
||||
...restJsonData,
|
||||
},
|
||||
@@ -238,6 +239,44 @@ export const ConfigEditor = (props: Props) => {
|
||||
</Field>
|
||||
</ConfigSubSection>
|
||||
|
||||
<ConfigSubSection title="Query Options">
|
||||
<Field
|
||||
label={
|
||||
<Label>
|
||||
<EditorStack gap={0.5}>
|
||||
<span>Query Timeout</span>
|
||||
<Tooltip
|
||||
content={
|
||||
<span>
|
||||
Maximum execution time in seconds for database queries initiated by the plugin. Queries
|
||||
exceeding this limit will be automatically terminated. Default is 60 seconds.
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Icon name="info-circle" size="sm" />
|
||||
</Tooltip>
|
||||
</EditorStack>
|
||||
</Label>
|
||||
}
|
||||
>
|
||||
<Input
|
||||
width={40}
|
||||
type="number"
|
||||
value={options.jsonData.queryTimeout}
|
||||
placeholder="60"
|
||||
onChange={(event) => {
|
||||
onOptionsChange({
|
||||
...options,
|
||||
jsonData: {
|
||||
...options.jsonData,
|
||||
queryTimeout: parseInt(event.currentTarget.value, 10) || undefined,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</ConfigSubSection>
|
||||
|
||||
<ConfigSubSection title="Trends">
|
||||
<Field label="Enable Trends">
|
||||
<Switch
|
||||
|
||||
@@ -14,6 +14,7 @@ export type ZabbixDSOptions = {
|
||||
trendsRange: string;
|
||||
cacheTTL: string;
|
||||
timeout?: number;
|
||||
queryTimeout?: number;
|
||||
dbConnectionEnable: boolean;
|
||||
dbConnectionDatasourceId?: number;
|
||||
dbConnectionDatasourceName?: string;
|
||||
|
||||
84
yarn.lock
84
yarn.lock
@@ -1438,16 +1438,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@es-joy/jsdoccomment@npm:~0.76.0":
|
||||
version: 0.76.0
|
||||
resolution: "@es-joy/jsdoccomment@npm:0.76.0"
|
||||
"@es-joy/jsdoccomment@npm:~0.79.0":
|
||||
version: 0.79.0
|
||||
resolution: "@es-joy/jsdoccomment@npm:0.79.0"
|
||||
dependencies:
|
||||
"@types/estree": "npm:^1.0.8"
|
||||
"@typescript-eslint/types": "npm:^8.46.0"
|
||||
"@typescript-eslint/types": "npm:^8.52.0"
|
||||
comment-parser: "npm:1.4.1"
|
||||
esquery: "npm:^1.6.0"
|
||||
jsdoc-type-pratt-parser: "npm:~6.10.0"
|
||||
checksum: 10c0/8fe4edec7d60562787ea8c77193ebe8737a9e28ec3143d383506b63890d0ffd45a2813e913ad1f00f227cb10e3a1fb913e5a696b33d499dc564272ff1a6f3fdb
|
||||
esquery: "npm:^1.7.0"
|
||||
jsdoc-type-pratt-parser: "npm:~7.0.0"
|
||||
checksum: 10c0/f5102197cf02bede52115f38569c7de2eee82096fe2c81a6d678f24796cd82f60d074ea19d3b9dd9dc1c55b3cafdd05e1b70595ef4eb6198c2a4b405313127d9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3567,7 +3567,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@testing-library/dom@npm:^10.4.1":
|
||||
"@testing-library/dom@npm:10.4.1":
|
||||
version: 10.4.1
|
||||
resolution: "@testing-library/dom@npm:10.4.1"
|
||||
dependencies:
|
||||
@@ -3839,19 +3839,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/lodash@npm:4.17.21":
|
||||
version: 4.17.21
|
||||
resolution: "@types/lodash@npm:4.17.21"
|
||||
checksum: 10c0/73cb006e047d8871e9d63f3a165543bf16c44a5b6fe3f9f6299e37cb8d67a7b1d55ac730959a81f9def510fd07232ff7e30e05413e5d5a12793baad84ebe36c3
|
||||
"@types/lodash@npm:4.17.22":
|
||||
version: 4.17.22
|
||||
resolution: "@types/lodash@npm:4.17.22"
|
||||
checksum: 10c0/8cef39191f00eaf5714727b1e0528f2ad89bc017e3850807de1c3c3d82716c48c2fc84d15323a904e25f8070b7e792c2cf731e4403cbb8497d1b16d5ae99b016
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:*, @types/node@npm:25.0.3, @types/node@npm:>=13.7.0":
|
||||
version: 25.0.3
|
||||
resolution: "@types/node@npm:25.0.3"
|
||||
"@types/node@npm:*, @types/node@npm:25.0.5, @types/node@npm:>=13.7.0":
|
||||
version: 25.0.5
|
||||
resolution: "@types/node@npm:25.0.5"
|
||||
dependencies:
|
||||
undici-types: "npm:~7.16.0"
|
||||
checksum: 10c0/b7568f0d765d9469621615e2bb257c7fd1953d95e9acbdb58dffb6627a2c4150d405a4600aa1ad8a40182a94fe5f903cafd3c0a2f5132814debd0e3bfd61f835
|
||||
checksum: 10c0/e92f8e29e17ff2d75f774233cad5b96bf7b253d24979162e1fff85993509a3511afe15a456217881f8e59fd5ff0b0d86067e33f57d599d1939a6d73c4f4806c7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -4092,7 +4092,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:8.52.0, @typescript-eslint/types@npm:^8.46.0, @typescript-eslint/types@npm:^8.52.0":
|
||||
"@typescript-eslint/types@npm:8.52.0, @typescript-eslint/types@npm:^8.52.0":
|
||||
version: 8.52.0
|
||||
resolution: "@typescript-eslint/types@npm:8.52.0"
|
||||
checksum: 10c0/ad93803aa92570a96cc9f9a201735e68fecee9056a37563c9e5b70c16436927ac823ec38d9712881910d89dd7314b0a40100ef41ef1aca0d42674d3312d5ec8e
|
||||
@@ -6636,18 +6636,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-jsdoc@npm:61.5.0":
|
||||
version: 61.5.0
|
||||
resolution: "eslint-plugin-jsdoc@npm:61.5.0"
|
||||
"eslint-plugin-jsdoc@npm:62.0.0":
|
||||
version: 62.0.0
|
||||
resolution: "eslint-plugin-jsdoc@npm:62.0.0"
|
||||
dependencies:
|
||||
"@es-joy/jsdoccomment": "npm:~0.76.0"
|
||||
"@es-joy/jsdoccomment": "npm:~0.79.0"
|
||||
"@es-joy/resolve.exports": "npm:1.2.0"
|
||||
are-docs-informative: "npm:^0.0.2"
|
||||
comment-parser: "npm:1.4.1"
|
||||
debug: "npm:^4.4.3"
|
||||
escape-string-regexp: "npm:^4.0.0"
|
||||
espree: "npm:^10.4.0"
|
||||
esquery: "npm:^1.6.0"
|
||||
espree: "npm:^11.0.0"
|
||||
esquery: "npm:^1.7.0"
|
||||
html-entities: "npm:^2.6.0"
|
||||
object-deep-merge: "npm:^2.0.0"
|
||||
parse-imports-exports: "npm:^0.2.4"
|
||||
@@ -6656,7 +6656,7 @@ __metadata:
|
||||
to-valid-identifier: "npm:^1.0.0"
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
|
||||
checksum: 10c0/fabb04f6efe58a167a0839d3c05676a76080c6e91d98a269fa768c1bfd835aa0ded5822d400da2874216177044d2d227ebe241d73e923f3fe1c08bafd19cfd3d
|
||||
checksum: 10c0/9558f9a05109f5eab9433225240f2ac36407b47694731e7ad1f6edb995c5616e51b7475b05409d230dc859ba4ac1f77dc5ed409e16fadf4c454305eab72695bf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -6757,6 +6757,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-visitor-keys@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "eslint-visitor-keys@npm:5.0.0"
|
||||
checksum: 10c0/5ec68b7ae350f6e7813a9ab469f8c64e01e5a954e6e6ee6dc441cc24d315eb342e5fb81ab5fc21f352cf0125096ab4ed93ca892f602a1576ad1eedce591fe64a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-webpack-plugin@npm:5.0.2":
|
||||
version: 5.0.2
|
||||
resolution: "eslint-webpack-plugin@npm:5.0.2"
|
||||
@@ -6834,6 +6841,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"espree@npm:^11.0.0":
|
||||
version: 11.0.0
|
||||
resolution: "espree@npm:11.0.0"
|
||||
dependencies:
|
||||
acorn: "npm:^8.15.0"
|
||||
acorn-jsx: "npm:^5.3.2"
|
||||
eslint-visitor-keys: "npm:^5.0.0"
|
||||
checksum: 10c0/1e07fdb2a135bb9996a4b23baad51980dde7bcdf4d7115cdec06437663790f4bbe3416eb560fc7dc7330c01a6006f789722f1e5b243208f4cb6e054efef57afd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"esprima@npm:^4.0.1":
|
||||
version: 4.0.1
|
||||
resolution: "esprima@npm:4.0.1"
|
||||
@@ -6844,7 +6862,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"esquery@npm:^1.5.0, esquery@npm:^1.6.0":
|
||||
"esquery@npm:^1.5.0, esquery@npm:^1.7.0":
|
||||
version: 1.7.0
|
||||
resolution: "esquery@npm:1.7.0"
|
||||
dependencies:
|
||||
@@ -7561,13 +7579,13 @@ __metadata:
|
||||
"@swc/helpers": "npm:0.5.18"
|
||||
"@swc/jest": "npm:0.2.39"
|
||||
"@tanstack/react-table": "npm:8.21.3"
|
||||
"@testing-library/dom": "npm:^10.4.1"
|
||||
"@testing-library/dom": "npm:10.4.1"
|
||||
"@testing-library/jest-dom": "npm:6.9.1"
|
||||
"@testing-library/react": "npm:16.3.1"
|
||||
"@types/grafana": "github:CorpGlory/types-grafana"
|
||||
"@types/jest": "npm:30.0.0"
|
||||
"@types/lodash": "npm:4.17.21"
|
||||
"@types/node": "npm:25.0.3"
|
||||
"@types/lodash": "npm:4.17.22"
|
||||
"@types/node": "npm:25.0.5"
|
||||
"@types/react": "npm:18.3.27"
|
||||
"@types/react-dom": "npm:18.3.7"
|
||||
"@typescript-eslint/eslint-plugin": "npm:8.52.0"
|
||||
@@ -7578,7 +7596,7 @@ __metadata:
|
||||
css-loader: "npm:7.1.2"
|
||||
eslint: "npm:9.39.2"
|
||||
eslint-config-prettier: "npm:10.1.8"
|
||||
eslint-plugin-jsdoc: "npm:61.5.0"
|
||||
eslint-plugin-jsdoc: "npm:62.0.0"
|
||||
eslint-plugin-prettier: "npm:5.5.4"
|
||||
eslint-plugin-react: "npm:7.37.5"
|
||||
eslint-plugin-react-hooks: "npm:7.0.1"
|
||||
@@ -9030,10 +9048,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsdoc-type-pratt-parser@npm:~6.10.0":
|
||||
version: 6.10.0
|
||||
resolution: "jsdoc-type-pratt-parser@npm:6.10.0"
|
||||
checksum: 10c0/8ea395df0cae0e41d4bdba5f8d81b8d3e467fe53d1e4182a5d4e653235a5f17d60ed137343d68dbc74fa10e767f1c58fb85b1f6d5489c2cf16fc7216cc6d3e1a
|
||||
"jsdoc-type-pratt-parser@npm:~7.0.0":
|
||||
version: 7.0.0
|
||||
resolution: "jsdoc-type-pratt-parser@npm:7.0.0"
|
||||
checksum: 10c0/3ede53c80dddf940a51dcdc79e3923537650f6fb6e9001fc76023c2d5cb0195cc8b24b7eebf9b3f20a7bc00d5e6b7f70318f0b8cb5972f6aff884152e6698014
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user