Repository navigation
Conversation
…rwarding Add [[outputs.http]] stanza (telegraf.outputs.fluentd) that POSTs performance analytics metrics to the local fluentd HTTP source at http://localhost:9880/delphix.metrics.platform, where fluentd routes them to third-party monitoring systems (Splunk, Datadog) via existing <match delphix.metrics.**> rules. - namepass: cpu, diskio, net, zfs, estat_nfs, estat_iscsi - flush_interval: 60s (matches performanceMetricsResolution = MINUTE) - data_format: json - Gated on FLUENTD_ENABLED flag file (same pattern as INFLUXDB_ENABLED) Add perf_fluentd enable|disable CLI to manage the flag and restart Telegraf. Update delphix-telegraf-service to include the fluentd output when the flag is set, and extend the STORAGE_IO_INPUTS inclusion guard so estat_nfs/estat_iscsi are collected whenever either InfluxDB or fluentd is enabled. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
dbshah12
requested review from
prakashsurya and
sebroy
and
a balanced review from Copilot
and removed request for
Copilot
October 27, 2026 13:49
…luentd
Add json_transformation = "metrics" to strip the {"metrics":[...]} wrapper
and send a top-level array that fluentd emits as individual metric records.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Change 1: Switch fluentd output to data_format=splunkmetric with splunkmetric_hec_routing=true. Produces one HEC event per metric field (metric_name, _value, _time) — same structure Java's InsightLogger sent. Requires app-gate PR #5043 (data_type metric in fluentd match block). Change 2: Add telegraf.global_tags with systemUniqueId/systemVersion, included when fluentd is enabled. delphix-telegraf-service exports DELPHIX_SYSTEM_UUID (get-system-uuid) and DELPHIX_SYSTEM_VERSION (get-appliance-version) at startup so Telegraf can interpolate them. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…processor Add processors.starlark (telegraf.processors.fluentd) that maps Telegraf measurements to Java InsightLogger metric names for fluentd output: system.cpu.util.pct = 100 - cpu.usage_idle (cpu-total) system.net.total.bytes = sum(bytes_recv+bytes_sent) across interfaces system.disk.ops.count = sum(reads+writes) across devices system.nfs.ops.count = estat_nfs.read_ops + write_ops system.iscsi.ops.count = estat_iscsi.read_ops + write_ops system.tcp.total.bytes = sum(inbytes+outbytes) across tcp endpoints Cross-device aggregation uses Telegraf's built-in state dict with 10s timestamp rounding to handle sub-second timing differences across devices. Each metric type keeps its original measurement flowing to InfluxDB; only the Java-named metrics reach the fluentd output (namepass updated). Verified on dbs-test.dlpxdc.co: all 4 testable metrics confirmed correct (nfs/iscsi require active NFS/iSCSI activity, not present on test engine). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
… findings Reconciled implementation with Java InsightLogger semantics (confirmed by reading dlpx-app-gate statcollector source): - net/diskio/tcp fields in Telegraf are cumulative kernel counters (same source as Java's /proc/net/dev etc.); Java computed deltas between consecutive polls. The starlark processor now does the same via `state`, keyed per interface / device / tcp endpoint. First-sample delta is 0; counter wrap guarded to 0. - cpu usage_idle is already a per-window percentage, keep as gauge. - estat_nfs/iscsi: fixed field name (iops(/s), not read_ops), multiplied by the 10s collection window to get ops-in-window. - All bucketing moved into starlark (no aggregator plugin) — basicstats would have suffixed field names with "_sum", corrupting the splunkmetric-derived metric_name. Uses nanosecond timestamps correctly (ts // 60e9). - systemUniqueId / systemVersion scoped to the compat metrics inside starlark via envsubst of DELPHIX_SYSTEM_UUID / DELPHIX_SYSTEM_VERSION — no longer Telegraf-global, so InfluxDB cardinality is unaffected (dropped telegraf.global_tags). - Added logger warnings for missing FLUENTD_OUTPUT / FLUENTD_PROCESSOR files (asymmetric fallback with InfluxDB path is now symmetric). - outputs.http: added timeout=10s and metric_buffer_limit=2048 so brief fluentd restarts don't lose data. - perf_fluentd: added status subcommand, idempotency check (no needless telegraf restart when flag is already in desired state), explicit die on touch failure. - Added explicit None guards for missing cpu/estat fields (previously returned 0, producing spurious 100% CPU or 0-ops metrics). Verified on dbs-test.dlpxdc.co: exactly one event per Java metric name per minute, with correct metric_name/_value/systemUniqueId/systemVersion fields matching Java InsightLogger format. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…rwarding Covers architecture, user controls, config assembly, metric transform pipeline, wire format comparison with Java InsightLogger, open questions, and a two-track stop-gap plan. Key context: DCT-managed engines already have zero fluentd forwarding (Java disabled on DCT add) — the Telegraf path is a bug fix for those customers, not a refactor. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Replace the complex multi-subgraph architecture diagram, sequence diagram, and flowchart with three focused diagrams: 1. Single end-to-end flow (what it does in one picture) 2. On/off switch flow (how enable/disable works) 3. Before/after comparison (what stays the same for customers) Also corrected "Why Replace It" to lead with DCT context as the real driver. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
83 lines total. Problem → Solution → Data flow diagram → What customers receive → 3 new files → 5 open questions → recommendation table. Everything needed for a fast decision, nothing else. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Keep the doc crisp but spell out the end-to-end flow in 5 numbered steps with context a reader without background can follow. Drop the open questions section — those are tracked separately. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…onfluence + Slack Explain the broader initiative (Telegraf as single collector for DCT engine dashboards), why that initiative disables Java (and silently kills Splunk forwarding), what we're building to restore it, the backward-compat matrix, the one acceptable compromise (data sub-counters), and per-customer migration cost. Links to the DCT performance analytics design page and the Slack thread where the trade-offs were negotiated with Seb. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…for review Reference-PRs table at the top of the doc links to the sample implementation alongside the design, so reviewers can see the exact Starlark transform, CLI, Fluentd template, and FluentServiceImpl lifecycle wiring that this doc describes. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ead) Design document is now the source-of-truth artefact at: https://perforce.atlassian.net/wiki/spaces/DLXEN/pages/3722117178 Keeping an in-repo copy risks drift; the Confluence page is linked from the PR description. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…nt silent event loss splunkmetric_hec_routing serializes a batch as raw-concatenated JSON objects with no delimiter or newline. Fluentd's <source @type http> JSON parser consumes only the first object per POST, silently dropping the rest — ~83% loss once all six compat metrics are flowing in production. use_batch_format=false serializes one metric per POST (6 small localhost requests per minute, negligible overhead) so every event lands. Verified on dbs-test.dlpxdc.co and ev-dev.dlpxdc.co: each POST body now contains exactly 1 top-level JSON object, all compat metric_names observed. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Each compat metric now carries rich data.* breakdown alongside _value,
closer to Java's pushInsightMetric payload shape:
system.cpu.util.pct 7 fields: usage_user/system/idle/iowait/
irq/softirq/steal (percentages)
system.net.total.bytes 4 fields: inBytes, outBytes, inPackets, outPackets
system.disk.ops.count 6 fields: reads, writes, bytesRead, bytesWritten,
readTime, writeTime
system.nfs.ops.count 6 fields: readOps, writeOps, read/writeLatency,
read/writeThroughput
system.iscsi.ops.count 6 fields: same shape as nfs
system.tcp.total.bytes 8 fields: inBytes, outBytes, retransmittedSegs,
sendWindowSize, congestionWindowSize,
receiveWindowSize, roundTripTime, connections
Note: round() triggers a Telegraf 1.40.2 starlark resolver bug ("undefined:
state" at compile time). We serialise numeric data via plain str() instead,
which is why percentages and rates show full float precision.
Verified end-to-end on ev-dev.dlpxdc.co and dbs-test.dlpxdc.co: processor
loads cleanly, all data.* fields appear in captured HEC events alongside
metric_name/_value/systemUniqueId/systemVersion.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…data.* fields Rename data.usage_* -> data.* on the cpu compat metric so Splunk reads e.g. data.idle, data.user, data.system (matching Java's naming convention) instead of data.usage_idle. State keys (cpu_d_usr etc.) are unchanged. Verified on ev-dev and dbs-test: processor loads cleanly, HEC fields now carry data.user / data.system / data.idle / data.iowait / data.irq / data.softirq / data.steal. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…-write-wins, guard envsubst Three focused fixes from PR #135 review: 1. Add order = 4 on [[processors.starlark]] so our processor runs AFTER the base-config storage_io processors (orders 1-3). Without this, the storage name=total filter may race with our estat accumulation, causing read + write + total rows all to be summed into nfs/iscsi counts (double-count). 2. Drop 5 TCP data.* fields that were last-write-wins across endpoints (sendWindowSize, congestionWindowSize, receiveWindowSize, roundTripTime, connections). Values reflected whichever connection happened to be the last one processed in the bucket, not any meaningful aggregate. The remaining 3 fields (data.inBytes, data.outBytes, data.retransmittedSegs) are true per-bucket deltas via cumulative_delta. 3. Validate DELPHIX_SYSTEM_UUID / DELPHIX_SYSTEM_VERSION against a safe char set ([A-Za-z0-9._+-]+) before envsubst inlines them into the Starlark triple-quoted TOML string. Unsafe values fall back to "unknown" with a syslog warning, so the service still starts (metrics tag identity as unknown rather than Telegraf failing to parse the config). Verified end-to-end on ev-dev.dlpxdc.co and dbs-test.dlpxdc.co: - Both engines load cleanly - All 6 compat metrics still emitting (system.cpu.util.pct through system.tcp.total.bytes) - TCP now has 3 data.* fields (previously 8); other metrics unchanged - Identity tags still present with real UUID/version values Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Jira
DLPX-100030 — part of epic APIGW-12274
Design
Telegraf → Fluentd Metric Forwarding (Backward-Compat for DCT-Managed Engines) — kept up to date, source of truth for the full field matrix and the review-driven decisions.
Companion app-gate PR: delphix/dlpx-app-gate#5043 (fluentd HTTP source + record_transformer that nests
data: {}and the Java passthrough)Background
Adding a DE to DCT turns off Java analytics on the engine so DCT's own Grafana dashboards aren't fed from two collectors at once. One side effect of that
analyticsManager.stop()is thatpushInsightMetric— the long-running path that pushed six KPI metrics into Fluentd, from where customers' Splunk / Datadog / Dynatrace integrations picked them up — also stops. Those customers see nothing in their monitoring tools, with no obvious signal that anything changed.Problem
Telegraf is already running on every engine and already collecting the raw inputs we need. What was missing: an HTTP output to Fluentd, a transform that reshapes the raw Telegraf metrics into the exact event shape customer dashboards were built against, and a way to flip the whole thing on and off from the setup screen.
Solution
The PR adds three files and modifies two.
telegraf/telegraf.outputs.fluentd— HTTP output pointed atlocalhost:9880.data_format = "splunkmetric"withsplunkmetric_hec_routing = truegives us the HEC envelope that app-gate's record_transformer expects.use_batch_format = falseis the subtle but important bit: the batched splunkmetric serializer concatenates JSON objects without a delimiter, and Fluentd's@type httpJSON parser silently truncates everything after the first object — one POST per metric avoids that landmine entirely. 60s flush, 10s timeout, 2048 metric buffer so a short Fluentd blip doesn't lose data.telegraf/telegraf.processors.fluentd— Starlark processor. Explicitorder = 4so it runs after the base-config storage_io processors (otherwise thename=totalrow from estat could land in our accumulators alongside the read + write rows and double-count NFS/iSCSI). Maps six Telegraf measurements to the Java metric names and matches Java's push semantics:metric_namesystem.cpu.util.pctinputs.cpu(cpu-total)100 - usage_idleper 60 ssystem.net.total.bytesinputs.netbytes_recv + bytes_sentover 60 ssystem.disk.ops.countinputs.diskioreads + writesover 60 ssystem.nfs.ops.countinputs.execd(estat nfs -jm 10)iops(/s) × 10across read + write rows over 60 ssystem.iscsi.ops.countinputs.execd(estat iscsi -jm 10)system.tcp.total.bytesinputs.execd(connstat-stats.sh)inbytes + outbytesover 60 sEach compat metric carries a
data.*breakdown that gets nested into a Java-shapeddata: {}object by the record_transformer in app-gate #5043: 7 fields for CPU, 4 for net, 6 for disk, 6 each for NFS/iSCSI, 3 for TCP — 35 total.systemUniqueId/systemVersionare injected per compat metric (not Telegraf-global, so InfluxDB cardinality is unaffected), with values substituted at config-regen time from env vars the service script exports.telegraf/perf_fluentd—enable | disable | statusCLI installed to/usr/bin/. Manages/etc/telegraf/FLUENTD_ENABLEDand restartsdelphix-telegraf. Idempotent (no-op when the flag is already in the desired state so we don't bounce the service for no reason), dies loudly ontouchfailure. Off by default; app-gate wiresperf_fluentd enableinto the 3rd-party integration lifecycle in #5043.telegraf/delphix-telegraf-service(modified) — exportsDELPHIX_SYSTEM_UUIDandDELPHIX_SYSTEM_VERSIONfromget-system-uuid/get-appliance-version, validates them against a safe char class beforeenvsubstinlines them into the Starlark triple-quoted TOML string (bad chars fall back to"unknown"with a syslog warning rather than failing to boot). Includes the fluentd fragments when the flag is set; the storage_io inputs are now included when either InfluxDB or fluentd is enabled (previously only InfluxDB). Missing-file warnings fire for both outputs symmetrically. Discard fallback only when neither output is configured.debian/rules(modified) — installsperf_fluentd. The two config fragments are picked up by the existingtelegraf/telegraf*glob.Backward compatibility
The full field matrix is in the design doc §6. In short:
metric_name,_value,_time,event: "metric",type: "g",systemUniqueId,systemVersion, 1-event/minute cadence, and the nesteddata: {}breakdown all match Java's shape. Dataset and capacity events (system.dataset.total.bytes,system.capacity.consumer.size,system.capacity.source.size) flow through unchanged via Java's untouchedlogMetric/pushInsightMetricspaths — only the KPIpushInsightMetricsingular was removed in app-gate.What customers do lose: TCP per-connection dimensions (
data.service,data.localAddress,data.remoteAddress, window sizes, RTT) because the aggregatedsystem.tcp.total.bytescan't preserve them; andperformanceMetricsResolution = SECOND(hardcoded 60s bucket). Customer migration cost: Splunk HEC users do nothing (template change ships in #5043); Datadog (×2) and Dynatrace (×1) customers add a 5-line<source @type http port 9880>stanza to their custom Fluentd template.Review-driven changes
Three Copilot findings fixed in this PR, four more accepted and documented as follow-ups in the design doc §6.
Fixed in the code:
order = 4on the Starlark block) — Copilot #4409213790data.*cut from 8 fields to 3 — the five I dropped (send/congestion/receive window sizes, RTT, connections) were last-write-wins across endpoints and had no meaningful value at the aggregated levelenvsubstsafe-char guard on UUID / version in the service scriptAccepted and documented (not blocking):
connstat-stats.shendpoint totals are non-monotonic (socket close shrinks the aggregate), so bytes from a closing session are undercounted. Rare on Delphix workloads; follow-up to make connstat emit true cumulative counters. Copilot #4409213874iops(/s) * 10loses precision below one op per second (bcchelper does integer division)._valueanddata.*share the same source so they stay internally consistent. Copilot #4409213850debian/tests/autopkgtest or Actions job that generates the config and runstelegraf --testagainst fixture input.Testing
Deployed to
ev-dev.dlpxdc.coanddbs-test.dlpxdc.coand captured end-to-end:perf_fluentd enable|disable|statusbehaves correctly across all state transitions; idempotent reruns are no-ops.telegraf.confcorrectly for every flag combination;envsubstsubstitutes the real UUID/version into the Starlark source; missing-file warnings fire as expected.:9880and confirmed each is one JSON object with the full HEC envelope + 35data.*fields populated.qa-splunk.ops.delphix.com,index=suyash_metrics: all six KPI events arrive with correctmetric_name,_value, nesteddata: {},systemUniqueId,systemVersion. Dataset and capacity events pass through from Java with their flat schema preserved. No null events once the record_transformer fallback landed in #5043.Live samples for each metric_name are in the design doc §10.