Skip to content
File integration · How-to Intermediate

Monitor a file-drop integration (hot folder) with OpenTelemetry

Turn each file that lands in a watched folder into a trace, and the folder's backlog into a metric — so a stuck or slow file-based integration shows up in Sluicio.

SLSluicio team 8 min read Updated Jun 2026

File drops are still everywhere in integration: an SFTP upload, an export written to a share, a partner dropping a nightly batch. They fail quietly — a file lands and just sits there. This guide makes a hot folder observable two ways: a trace per file so you can follow one document end-to-end, and a folder-depth metric so a growing backlog is impossible to miss.

  • A trace per file — best when you control the processor and want per-file timing, attributes (size, partner, type) and failures you can search.
  • Folder metrics — best when you can’t touch the code: just watch how many files are waiting and how old the oldest one is.

Wrap the per-file handler in a span. The attributes you set here become searchable fields in Sluicio, so add the ones you’d want to filter a failure by. (For SDK setup, see Instrument a service.)

FileProcessor.java
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
Tracer tracer = GlobalOpenTelemetry.getTracer("file-drop");
void processFile(Path file) throws IOException {
Span span = tracer.spanBuilder("file.process").startSpan();
try (var scope = span.makeCurrent()) {
span.setAttribute("file.name", file.getFileName().toString());
span.setAttribute("file.size", Files.size(file));
handle(file);
} catch (Exception e) {
span.recordException(e);
span.setStatus(StatusCode.ERROR); // shows as a failed message
throw e;
} finally {
span.end();
}
}

Each file becomes one trace. A failed file is a failed span you can find — and re-drive — from message search.

Option B — Folder metrics with the Collector

Section titled “Option B — Folder metrics with the Collector”

No code path: the Collector’s file_stats receiver reports on the files matching a glob, so you get a live count (the backlog) and each file’s modification time (to find the oldest, stuck file).

This config targets Collector v0.152.0 or later. On older Collectors the receiver is called filestats and the exporter otlphttp.

otel-collector-config.yaml
receivers:
file_stats:
include: '/data/inbound/*'
collection_interval: 60s
exporters:
otlp_http/sluicio:
endpoint: https://your-instance-name.sluicio.com
headers:
authorization: Bearer ${env:SLUICIO_INGEST_KEY}
service:
pipelines:
metrics:
receivers: [file_stats]
exporters: [otlp_http/sluicio]
Terminal window
docker run --rm \
-v "$(pwd)/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml" \
-v /data/inbound:/data/inbound:ro \
-e SLUICIO_INGEST_KEY \
otel/opentelemetry-collector-contrib:latest
MetricWhat it tells you
file.countFolder depth — how many files are waiting.
file.mtimePer-file modification time — the oldest one is your stuck file.
file.sizeFile size — useful to spot a truncated or zero-byte drop.
  • Backlog buildingfile.count stays above your threshold for N minutes.
  • Stuck file — the oldest file’s age (now − min file.mtime) exceeds the batch window. This fires even when the count is low, which is exactly when a single wedged file would otherwise go unnoticed.