Skip to main content

Fusion task metrics

Every task that runs with Fusion writes a metrics file that records how the cache behaved, how the cloud object store responded, how much data moved, and where requests stalled. Read the file with zcat and jq to answer most "the pipeline is slow" and "the task hangs" questions without opening a support ticket.

note

If a task produced no metrics file, the most likely cause is a Fusion version that predates these releases. See The metrics file is missing for the other causes.

Metric families

Metrics are grouped into five families by name prefix. Each family answers a different question about a task.

FamilyName prefixWhat it answers
Object storefusion_backend_How the cloud object store (S3, Azure Blob Storage, or Google Cloud Storage) responded to Fusion. Use this for throttling, permission errors, cross-region latency, and total data transferred.
Cachefusion_cache_Whether Fusion could reuse data it already had locally, or had to fetch it again. Use this to decide whether the node's local disk is large enough for the working set.
File systemfusion_fs_What the application asked Fusion to do through the mount, how long Fusion took to answer, and whether any request was never answered. Use this to tell an application-side hang apart from a Fusion-side stall.
Chunk transferfusion_chunk_How the pieces of large files moved between the node and the object store. Use this for stalled or repeatedly retried transfers.
System healthfusion_health_Resource state on the node itself, such as mount uptime, memory, open file handles, and free space on the cache device. Use this for local disk exhaustion.

Metric catalog

Counters and histograms are cumulative: every sample restates the running total since the mount started, so the last record of a series is the end-of-task total and the difference between two consecutive samples is the activity during that interval. Other values instead report a point-in-time level that can rise and fall between samples: read the last value as the final state, or take the min/max across samples, never a difference.

A metric that never fired is absent from the file. Treat a missing series as zero, not as a broken file. A healthy task has no eviction series and no throttling retries.

Object store (fusion_backend_*)

These metrics count and time every request Fusion makes to the cloud object store.

MetricTypeExpected valueAn anomalous reading indicates
fusion_backend_requests_totalCounterAlmost all series carry outcome="ok".A sustained share of outcome="error" points at permissions, credentials, or provider faults. Check the error_code label for the category.
fusion_backend_requests_retries_totalCounterAbsent or near zero.Any sustained count with retry_reason="throttling" means the provider rate-limited you. See The object store is throttling requests.
fusion_backend_requests_bytes_totalCounterComparable to the input and output volume of the process.Far more bytes downloaded than the inputs contain means data was fetched more than once. Cross-check the cache hit ratio.
fusion_backend_requests_latency_secondsHistogramSame-region time to first byte sits in the tens of milliseconds.A sustained mean in the hundreds of milliseconds indicates networking issues.
fusion_backend_requests_bytesHistogramReflects the read sizes the process issues.A distribution concentrated in the smallest buckets means many small requests where fewer large ones would be cheaper.
fusion_backend_requests_in_flightGaugeReturns to 0 when the task goes quiet.A non-zero value in the final sample means a request started and never completed.

Fusion records a request that returns 404 as outcome="expected-miss" rather than error, because a negative lookup is normal. It records a request the caller abandoned as outcome="cancelled". Neither counts toward the error rate.

Cache (fusion_cache_*)

Cache tiers are named by access type:

  • lookup resolves whether a path exists.
  • directory tracks directory-listing freshness.
  • data is the local cache of file content.
MetricTypeExpected valueAn anomalous reading indicates
fusion_cache_hits_totalCounterHigh relative to misses on data for workloads that re-read their inputs.A low hit ratio alone can mean a streaming workload that reads everything once.
fusion_cache_misses_totalCounterLow relative to hits on re-reading workloads.A low hit ratio combined with a large eviction count is the cache thrash signature.
fusion_cache_evictions_totalCounterAbsent on a task whose working set fits the local disk.A large count means data was cached, discarded under disk pressure, and fetched again. See The cache is thrashing.
fusion_cache_io_bytes_totalCounterRoughly tracks the data the task read and wrote.No fixed baseline. Compare it against fusion_backend_requests_bytes_total to see how much traffic the cache absorbed.
fusion_cache_entriesGaugeGrows during the task and does not fall on eviction.Unbounded growth well beyond the number of files touched. The gauge counts tracking slots, not cache occupancy.

File system (fusion_fs_*)

The operation label is the virtual file system (VFS) handler name, such as read, write, lookup, getattr, open, or readdir.

MetricTypeExpected valueAn anomalous reading indicates
fusion_fs_requests_totalCounterProportional to the work the process performs.Millions of read operations against a small byte total is the tiny-read signature. See The tool issues many tiny reads.
fusion_fs_requests_bytes_totalCounterMatches the volume of data the process reads and writes.Divide by the read count. A mean of a few hundred bytes per read means the tool issues many small random reads, each paying a round trip through FUSE.
fusion_fs_requests_latency_secondsHistogramCached metadata operations complete in single-digit milliseconds.A long tail on read usually traces back to object store latency rather than to Fusion. Compare with the object store histogram.
fusion_fs_requests_in_flightGaugeSmall and fluctuating. Returns to 0 when the task goes quiet.A value that only ever rises means requests arrive and are never answered. The operation label narrows the stall to a call type.
fusion_fs_requests_in_flight_oldest_secondsGaugeNear zero on a healthy mount.A value that climbs sample after sample into hundreds of seconds without recovering means a request is stuck inside Fusion or its backend. Open a support ticket. A value near zero during an apparent hang means nothing is calling Fusion. The stall is then in the application or the environment.

Chunk transfer (fusion_chunk_*)

Fusion splits large files into chunks. These metrics track how those chunks move between the node and the object store.

MetricTypeExpected valueAn anomalous reading indicates
fusion_chunk_transfers_totalCounterScales with the volume of large-file data moved.No fixed baseline. Use it as the denominator for the stall and retry counters.
fusion_chunk_stalls_totalCounterAbsent.Any count means a transfer stopped mid-stream and the stall watchdog intervened.
fusion_chunk_retries_totalCounterAbsent or a small fraction of transfers.A high ratio to fusion_chunk_transfers_total means transfers repeatedly fail and resume. The task slows but does not fail.
fusion_chunk_errors_totalCounterAbsent, except for error_type="canceled".Counts under stall, timeout, transient, or exhausted are real failures. Exclude canceled, which marks a normal caller interruption.
fusion_chunk_transfers_in_flightGaugeReturns to 0 when the task goes quiet.A non-zero value in the final sample means a transfer never finished.
fusion_chunk_size_bytesHistogramConcentrated near the configured chunk size for sequential reads.A distribution skewed to small sizes means fragmented or random access rather than streaming.
fusion_chunk_queue_wait_secondsHistogramMilliseconds when transfer capacity is sufficient.Seconds of queue wait means transfers are backing up behind available bandwidth or concurrency.
fusion_chunk_prefetch_drops_totalCounterLow or absent.A high count means the prefetcher is shedding work because it cannot keep up. Read it alongside the queue wait histogram.

System health (fusion_health_*)

These metrics describe the node and the mount rather than individual requests.

MetricTypeExpected valueAn anomalous reading indicates
fusion_health_uptime_secondsGaugeRises monotonically and roughly matches the task duration.A final value far below the task duration means the mount restarted mid-task.
fusion_health_goroutinesGaugeStable after the mount warms up.Unbounded growth suggests work accumulating that never completes.
fusion_health_memory_bytesGaugePlateaus once the workload reaches steady state. Labeled heap, stacks, and other.A heap value that climbs without plateauing risks an out-of-memory kill of the task.
fusion_health_open_file_handlesGaugeReturns to 0 when the task goes quiet.A value that only ever rises means the application opens files without closing them.
fusion_health_disk_bytesGaugefree stays well clear of zero for the whole task.free bottoming out near zero means the cache device filled up. This usually appears alongside the cache thrash signature.
fusion_health_mount_init_secondsHistogramSeconds.A value in the tens of seconds delays every task in the run.
fusion_health_shutdown_flush_secondsHistogramProportional to the volume of output still to upload at task end.A long flush relative to the task runtime means output upload, not computation, dominates the task.

Download the metrics file

Fusion writes the metrics to the task work directory, next to .fusion.log:

<task work directory>/.fusion/metrics.jsonl.gz

Find the task work directory on the task detail page in Seqera Platform, under Work directory. It also appears near the top of .nextflow.log.

Download the file with your cloud provider's CLI:

# AWS
aws s3 cp s3://<bucket>/<workdir>/.fusion/metrics.jsonl.gz .

# Azure
az storage blob download --account-name <account> -c <container> \
-n '<workdir>/.fusion/metrics.jsonl.gz' -f metrics.jsonl.gz

# Google Cloud
gcloud storage cp gs://<bucket>/<workdir>/.fusion/metrics.jsonl.gz .

The file is a gzip stream of JSON records, sampled every 10 seconds by default.

Inspect the file

The header record identifies the Fusion version, the mount start time in Unix nanoseconds, and the host:

zcat metrics.jsonl.gz | head -1 | jq .

List which metrics the file contains:

zcat metrics.jsonl.gz | jq -r '.metric // empty' | sort -u

Check for a closing record:

zcat metrics.jsonl.gz | jq -c 'select(.type=="closing")'

If nothing comes back, the task was killed before Fusion could shut down cleanly. Look for a spot reclaim, an out-of-memory kill, or a hard cancellation.

Diagnostic queries

Each query returns the end-of-task total for a specific failure signature. Run them against a downloaded metrics.jsonl.gz.

The object store is throttling requests

Tasks look slow but keep making progress, and nothing in the task log looks wrong.

zcat metrics.jsonl.gz | jq -s '[.[] |
select(.metric=="fusion_backend_requests_retries_total"
and .labels.retry_reason=="throttling")] |
group_by(.labels) | map(last |
{provider: .labels.provider, operation: .labels.operation, retries: .value})'

Any sustained non-zero count means the provider pushed back and Fusion had to retry. Corroborate it by breaking the failed requests down by status code and category. RateLimited appears as 429 or 503:

zcat metrics.jsonl.gz | jq -s '[.[] |
select(.metric=="fusion_backend_requests_total"
and .labels.outcome=="error")] |
group_by(.labels) | map(last | {labels, value})'

To resolve, lower the task parallelism, spread the data across more prefixes, or ask the provider for a rate limit increase.

The cache is thrashing

The working set does not fit on the node's local disk. Fusion keeps evicting data it is about to need again.

zcat metrics.jsonl.gz | jq -s '
def lastval(name): [.[] |
select(.metric == name and .labels.cache_type == "data")] | last | .value;
{hits: lastval("fusion_cache_hits_total"),
misses: lastval("fusion_cache_misses_total"),
evictions: lastval("fusion_cache_evictions_total")} |
. + {hit_ratio: (.hits / (.hits + .misses))}'

A low hit ratio on its own can mean a streaming workload. The thrash signature is a low hit ratio combined with a large eviction count. To resolve, use a bigger local disk, an instance type with more NVMe, or fewer concurrent tasks per node.

The object store is far away

Every request pays a high fixed latency before the first byte arrives.

zcat metrics.jsonl.gz | jq -s '[.[] |
select(.metric=="fusion_backend_requests_latency_seconds"
and .labels.latency_type=="time_to_first_byte"
and .labels.operation=="GetObject")] |
last | {requests: .histogram.count,
mean_ttfb_seconds: (.histogram.sum / .histogram.count)}'

Same-region time to first byte sits in the tens of milliseconds. A mean in the hundreds of milliseconds points at distance or routing. To resolve, confirm that the bucket and the compute run in the same region. On AWS, check whether the VPC has an S3 gateway endpoint.

The tool issues many tiny reads

Some tools issue millions of small reads at random offsets. Each is cheap on a local disk but pays a round trip through FUSE on a Fusion mount.

zcat metrics.jsonl.gz | jq -s '
def lastval(name): [.[] |
select(.metric == name and .labels.operation == "read")] | last | .value;
{reads: lastval("fusion_fs_requests_total"),
bytes: lastval("fusion_fs_requests_bytes_total")} |
. + {mean_bytes_per_read: (.bytes / .reads)}'

Millions of reads with a mean of a few hundred bytes each is the signature. As a workaround for tools known to behave this way, copy the input to local scratch inside the process before running the tool. The small reads then come from local disk instead of the mount.

A request never completed

The task looks hung.

zcat metrics.jsonl.gz | jq -s '[.[] |
select(.metric=="fusion_fs_requests_in_flight_oldest_seconds") | .value] | max'

This gauge reads near zero on a healthy mount. A value that climbs sample after sample without recovering means a request is stuck inside Fusion or its backend. Collect the metrics file and .fusion.log, then open a support ticket.

The local disk filled up

The cache device ran out of space. This surfaces as eviction storms, slowdowns, or task failures late in the run.

zcat metrics.jsonl.gz | jq -s '[.[] |
select(.metric=="fusion_health_disk_bytes" and .labels.state=="free") |
.value] | min'

Free space bottoming out near zero confirms the cause. To resolve, size the node's disk to the working set. This often appears alongside the cache thrash signature.

Turn off metrics collection

There are two levels of opt-out.

Stop sending metrics to Seqera

On Seqera Cloud only, turn off Send Fusion metrics to Seqera on the compute environment, either when you create it or by editing an existing compute environment. Seqera will not retain any copy. Fusion continues to write .fusion/metrics.jsonl.gz to the task work directory for your own troubleshooting only.

The toggle is on by default for new Fusion-enabled compute environments only. Existing compute environments keep the setting they already have. This feature is not present on Enterprise deployments.

Disable collection entirely

To stop Fusion from writing the metrics file at all, set FUSION_METRICS_ENABLED=false in the task container environment. In nextflow.config:

process {
containerOptions = { "-e FUSION_METRICS_ENABLED=false" }
}

Fusion writes no metrics file at all.

note

Disabling metrics does not affect logging. Fusion always writes critical operational events, such as stall watchdog warnings and errors, to .fusion.log regardless of this setting.

Change the sampling interval

To reduce the sampling frequency instead of disabling collection, set FUSION_METRICS_SAMPLE_INTERVAL. It accepts a Go duration and defaults to 10s:

process {
containerOptions = { "-e FUSION_METRICS_SAMPLE_INTERVAL=60s" }
}

The metrics file is missing

If a task produced no .fusion/metrics.jsonl.gz, work through these causes in order:

CauseHow to confirm
The Fusion version is earlier than 2.6.4, or earlier than 2.5.15.Check the Fusion version reported in .fusion.log.
Collection was disabled with FUSION_METRICS_ENABLED=false.Check containerOptions in your Nextflow configuration.
A non-default output format is configured.FUSION_METRICS_FORMAT=log writes no file. The debug-only json-otel writes an uncompressed file that zcat refuses.
The node disappeared before Fusion could upload the file.Look for a spot reclaim or a hard kill on the task.

A file from an uncleanly ended task can also be truncated. In that case zcat prints everything up to the truncation point and then reports an error on stderr. That is expected, and every line it printed is valid.

Getting help

When you contact Seqera support about task performance, provide the following:

  • The metrics.jsonl.gz file for the affected task.
  • The .fusion.log file from the same task work directory.
  • The Fusion version and host from the metrics header record.
  • The cloud provider, the bucket region, and the compute region.
  • The Seqera Platform run URL, or the task work directory path.