UNPKG

openclaw-grafana-lens

Version:

OpenClaw plugin that gives AI agents full Grafana access — 18 composable tools for PromQL/LogQL/TraceQL queries, dashboard creation, alerting, SRE investigation, security monitoring, data collection pipeline management via Grafana Alloy (29 recipes), and

82 lines (81 loc) 3.92 kB
import { AlloyConfigBuilder, componentLabel, escapeString } from "../../config-builder.js"; import { buildProcessBlock, extractProcessingParams, PROCESSING_OPTIONAL_PARAMS } from "./_process-builder.js"; const recipe = { name: "docker-logs", category: "logs", signal: "logs", summary: "Collect Docker container logs and forward to Loki, with optional JSON/label processing", dashboardTemplate: null, credentialParams: [], requiredParams: [], optionalParams: [ { name: "containerNames", type: "string[]", description: "Only collect from these containers (empty = all)", default: [] }, { name: "excludeContainers", type: "string[]", description: "Exclude these containers", default: [] }, { name: "labels", type: "string", description: "Extra labels as key=value pairs" }, ...PROCESSING_OPTIONAL_PARAMS, ], generateConfig(pipelineId, params, targets, _pipelineName) { const containerNames = params.containerNames ?? []; const excludeContainers = params.excludeContainers ?? []; const discLabel = componentLabel(pipelineId, "discover"); const relabelLabel = componentLabel(pipelineId, "relabel"); const srcLabel = componentLabel(pipelineId, "docker"); const writeLabel = componentLabel(pipelineId, "write"); const needsRelabel = containerNames.length > 0 || excludeContainers.length > 0; const builder = new AlloyConfigBuilder(); builder.addBlock(`discovery.docker "${discLabel}" { host = "unix:///var/run/docker.sock" refresh_interval = "5s" }`); if (needsRelabel) { const rules = []; if (containerNames.length > 0) { const regex = containerNames.map((n) => escapeString(n)).join("|"); rules.push(` rule {\n source_labels = ["__meta_docker_container_name"]\n regex = "/?(${regex})"\n action = "keep"\n }`); } if (excludeContainers.length > 0) { const regex = excludeContainers.map((n) => escapeString(n)).join("|"); rules.push(` rule {\n source_labels = ["__meta_docker_container_name"]\n regex = "/?(${regex})"\n action = "drop"\n }`); } builder.addBlock(`discovery.relabel "${relabelLabel}" {\n targets = discovery.docker.${discLabel}.targets\n${rules.join("\n")}\n}`); } const targetsRef = needsRelabel ? `discovery.relabel.${relabelLabel}.output` : `discovery.docker.${discLabel}.targets`; // Wire: source → [process →] write const processing = buildProcessBlock(pipelineId, extractProcessingParams(params), `loki.write.${writeLabel}.receiver`); const forwardTo = processing ? processing.receiverRef : `loki.write.${writeLabel}.receiver`; builder.addBlock(`loki.source.docker "${srcLabel}" { host = "unix:///var/run/docker.sock" targets = ${targetsRef} forward_to = [${forwardTo}] labels = { source = "docker" } }`); if (processing) { builder.addBlock(processing.block); } builder.addBlock(`loki.write "${writeLabel}" { endpoint { url = "${escapeString(targets.lokiWriteUrl)}" } }`); return builder.build(pipelineId, "docker-logs", "docker-logs"); }, sampleQueries(_params, _jobName) { return { recentLogs: '{source="docker"}', errorLogs: '{source="docker"} |= "error"', logVolume: 'rate({source="docker"}[5m])', }; }, componentIds(pipelineId) { return [ `discovery.docker.${componentLabel(pipelineId, "discover")}`, `loki.source.docker.${componentLabel(pipelineId, "docker")}`, `loki.write.${componentLabel(pipelineId, "write")}`, ]; }, }; export default recipe;