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

@ -11,6 +11,7 @@ import {
MutationImportTemplateGroupsArgs,
MutationImportTemplatesArgs,
MutationImportUserRightsArgs,
MutationPushHistoryArgs,
Permission,
QueryAllDevicesArgs,
QueryAllHostGroupsArgs,
@ -34,6 +35,7 @@ import {TemplateDeleter} from "../execution/template_deleter.js";
import {HostValueExporter} from "../execution/host_exporter.js";
import {logger} from "../logging/logger.js";
import {ParsedArgs, ZabbixRequest} from "../datasources/zabbix-request.js";
import {ZabbixHistoryGetParams, ZabbixHistoryPushParams, ZabbixHistoryPushRequest, ZabbixQueryHistoryRequest} from "../datasources/zabbix-history.js";
import {
ZabbixCreateHostRequest,
ZabbixQueryDevices,
@ -257,6 +259,21 @@ export function createResolvers(): Resolvers {
}: any) => {
return TemplateImporter.importTemplates(args.templates, zabbixAuthToken, cookie)
},
pushHistory: async (_parent: any, args: MutationPushHistoryArgs, {
zabbixAuthToken,
cookie
}: any) => {
const result = await new ZabbixHistoryPushRequest(zabbixAuthToken, cookie)
.executeRequestThrowError(zabbixAPI, new ZabbixHistoryPushParams(args.values, args.itemid?.toString(), args.key ?? undefined, args.host ?? undefined));
return {
message: result.response === "success" ? "History pushed successfully" : "Some errors occurred",
data: result.data.map(d => ({
itemid: d.itemid,
error: Array.isArray(d.error) ? {message: d.error.join(", ")} : d.error
}))
}
},
deleteTemplates: async (_parent: any, args: MutationDeleteTemplatesArgs, {
zabbixAuthToken,
cookie

View file

@ -11,6 +11,7 @@ import {logger} from "../logging/logger.js";
import {zabbixAPI, zabbixDevelopmentToken} from "../datasources/zabbix-api.js";
import {WebSocketServer} from "ws";
import {useServer} from "graphql-ws/lib/use/ws";
import {Config} from "../common_utils.js";
const GRAPHQL_PATH = "/"
const GRAPHQL_PORT = 4000
@ -59,6 +60,25 @@ async function startApolloServer() {
};
},
},
// Request logging plugin
{
async requestDidStart(requestContext) {
if (Config.VERBOSITY > 0) {
logger.info(`GraphQL Request: ${requestContext.request.operationName || 'Unnamed Operation'}`);
if (requestContext.request.variables) {
logger.info(`Parameters: ${JSON.stringify(requestContext.request.variables, null, 2)}`);
}
}
return {
async willSendResponse(requestContext) {
if (Config.VERBOSITY > 1) {
logger.info(`GraphQL Response for ${requestContext.request.operationName || 'Unnamed Operation'}:`);
logger.info(JSON.stringify(requestContext.response.body, null, 2));
}
},
};
},
},
],
});