@saptools/cf-tail
A command line that tails every started app in a Cloud Foundry space at once and merges their logs into one timeline by timestamp, with filters by level, tenant, router status and time window.
When a request crosses several apps in one Cloud FoundrySAP BTP, Cloud Foundry RuntimeThe Cloud Foundry runtime of SAP BTP: memory for applications in a Cloud Foundry org, run from SAP's Java, Node.js and Python buildpacks or community buildpacks and managed with the standard Cloud Foundry tools.sap official, btp space, cf logs still shows one app per terminal. This command line discovers the started apps in a region, org and space, fetches their recent logs in parallel (four at a time by default) or streams them live, and merges the rows by timestamp with each row labelled by its app; a running stream re-runs cf apps every 30 seconds to pick up apps that start or stop. Rows can be filtered across apps by level, tenant, router status range and time window, cf-tail summary counts levels, statuses and tenants per app, and the current SAP email and password are redacted before anything is printed or saved. Parsing and per-app storage come from @saptools/cf-logs@saptools/cf-logsA command line and typed Node.js library that fetches and streams the logs of one Cloud Foundry app and parses them into structured rows.independent, btp, which it installs as a dependency, and any other secret an application logs is redacted only when passed with --extra-secret.
Facts
Where it sits
Who is behind it
In the atlas: maintains 18, contributes to 18@dongitranmaintainer
What it declares
Every artifact
- Type
- CLI
- Origin
- Independently maintained
- Runs on
- Cloud Foundry
As a CLI
- Distributed through
- npm
Connections
Seeing what a running service did, in a readable form
Log fetcher and parser for one Cloud Foundry app
A cross-platform JavaScript runtime that servers, command line tools and scripts written in JavaScript are run with. For the things here, the prerequisite a repository names when its build is a set of npm scripts.
Download
Install
npm add @saptools/cf-tailDerived from the package name. No recipe recorded; the README has the configuration.
Architecture
Download
cf CLI on the path.README
quoted from dongitran/saptools under MIT, read🛰️ @saptools/cf-tail
Tail every app in a Cloud Foundry space at once — chronologically merged, filtered, and redacted.
Built on top of @saptools/cf-logs. Discover all started apps in
a region/org/space, fetch their recent logs in parallel, and stream them live
into a single multiplexed feed with strong filtering and bounded local
persistence.
Install • Quick Start • CLI • Store • Security
✨ Features
- 📥 Space-wide snapshots — fetch recent logs for every started app in a CF space in parallel, with a configurable concurrency limit.
- 🧬 Chronological merge — every row carries its
appNameand rows from all apps are merged by timestamp into a single timeline. - 📡 Multiplexed live stream — one
cf-tail streamprocess tails every app at once, with per-app color, prefixed labels, and auto-rediscovery as apps appear or disappear. - 🎯 Powerful selection —
--apps a,b,--include-regex,--exclude,--exclude-regexto scope the fan-out. - 🧰 Cross-app filtering — level, search, source, tenant, status range,
stream (
out/err),--since/--untiltime windows,--max-rows. - 📊 Summary view —
cf-tail summaryaggregates level counts, source buckets, status buckets, tenants, first/last timestamps per app. - 🚨 Errors shortcut —
cf-tail errorsissnapshot --level erroracross the whole space. - 🔐 Redaction — SAP credentials are redacted before any output or
persistence; you can add custom secrets via
--extra-secretor programmatic options. - 🗃️ Bounded local store — aggregate snapshots cached at
~/.saptools/cf-tail-store.jsonwith atomic writes and locking. Per-app raw logs continue to live in the cf-logs store. - 🧪 Fake-backed e2e — discovery, snapshot, stream, summary flows all pass without live SAP access.
📦 Install
# Global CLI
npm install -g @saptools/cf-tail
# Or as a dependency
npm install @saptools/cf-tail
# pnpm add @saptools/cf-tail
# yarn add @saptools/cf-tail
Note
Requires Node.js >= 20 and the official
cfCLI onPATH.
Updates
Every command first checks npm for a newer @saptools/cf-tail (at most once an hour, one small request
with a 2-second timeout) and, when one exists, installs that exact version with the package manager
that owns the running binary and re-runs the command you typed on the new version. Both steps are
announced on stderr; nothing is printed when the install is already current:
cf-tail: updating 0.2.0 -> 0.3.0 ...
cf-tail: updated to 0.3.0; re-running the command
If the install cannot complete, one stderr line gives the manual command and the command runs on the
installed version; that version is not retried for a day. cf-tail self-update forces the check and
install now; cf-tail self-update --check only reports.
| Control | Effect |
|---|---|
SAPTOOLS_AUTO_UPDATE=on|notify|off | on (default) installs and re-runs; notify prints the manual command once per version; off never checks. Applies to every @saptools CLI. |
CF_TAIL_AUTO_UPDATE | same values, this CLI only; wins over the global variable |
SAPTOOLS_UPDATE_INTERVAL_MINUTES | minutes between checks (default 60; 0 checks on every run) |
SAPTOOLS_NPM_REGISTRY | registry to check and install from (default: npm's configured registry, then npmjs) |
SAPTOOLS_UPDATE_DEBUG=1 | explain on stderr why nothing happened |
The updater switches itself off in CI (CI set), under NODE_ENV=test or NO_UPDATE_NOTIFIER, when
the binary runs from a source checkout, an npm link or an npx cache, and inside the re-run itself.
It never writes to stdout, never asks for input, never uses sudo, and never moves onto a prerelease.
Its state lives in ~/.saptools/updates/.
🚀 Quick Start
# 1. Export credentials used for cf api/auth
export SAP_EMAIL="sample@example.com"
export SAP_PASSWORD="sample-password"
# 2. List every started app in a space
cf-tail apps --region ap10 --org sample-org --space sample
# 3. One-shot snapshot of every app, merged by timestamp
cf-tail snapshot --region ap10 --org sample-org --space sample
# 4. Live tail of every app, with per-app colors
cf-tail stream --region ap10 --org sample-org --space sample
🧰 CLI
Shared session flags
| Flag | Description |
|---|---|
--region <key> | CF region key such as ap10 |
--api-endpoint <url> | Explicit CF API endpoint instead of a region key |
--org <name> | CF org name |
--space <name> | CF space name |
--email <value> | Override SAP_EMAIL |
--password <value> | Override SAP_PASSWORD |
App-selection flags
| Flag | Description |
|---|---|
--apps <a,b> | Comma-separated app names to include (alias for --include) |
--include <name> | Include a specific app name (repeatable) |
--exclude <name> | Exclude a specific app name (repeatable) |
--include-regex <pattern> | Include apps matching the regex (repeatable) |
--exclude-regex <pattern> | Exclude apps matching the regex (repeatable) |
Row filter flags (snapshot, errors, summary, stream)
| Flag | Description |
|---|---|
--level <name> | trace, debug, info, warn, error, fatal, or all |
--search <text> | Case-insensitive substring filter against the searchable row text |
--source <text> | Filter rows whose CF source contains the given text |
--tenant <id> | Filter rows whose parsed router tenant id matches |
--status <range> | Filter router status: 500, 5xx, or 400-499 |
--stream <value> | Filter by out, err, or all |
--since <duration> | Keep rows newer than now - duration (e.g. 30s, 5m, 1h) |
--until <duration> | Drop rows older than now - duration |
--max-rows <count> | Maximum rows in the rendered output |
--newest-first | Render newest-first instead of oldest-first |
Output flags
| Flag | Description |
|---|---|
--json | Emit a single structured JSON object (snapshot, summary) |
--ndjson | Emit line-delimited JSON rows (snapshot, stream) |
--by-app | Group rendered rows by app instead of merged timeline |
--no-color | Disable ANSI colors. Honors NO_COLOR env; FORCE_COLOR overrides for non-TTY pipelines |
--show-source | Include the CF source segment in text output |
--truncate <chars> | Truncate text-mode messages longer than the given character count |
Redaction flags
| Flag | Description |
|---|---|
--extra-secret <value> | Add a custom redaction (repeatable). Each occurrence is replaced with *** in output and storage |
cf-tail apps
cf-tail apps \
--region ap10 \
--org sample-org \
--space sample \
--include-regex "^demo-" \
--exclude demo-canary \
--json
cf-tail snapshot
Fetches recent logs for every matching app in parallel, merges into a single chronological timeline, applies row filters, and optionally persists.
cf-tail snapshot \
--region ap10 \
--org sample-org \
--space sample \
--apps demo-app,api-app \
--level error \
--since 30m \
--max-rows 100 \
--json
| Snapshot-only flag | Description |
|---|---|
--save | Persist redacted per-app snapshots to the cf-logs store and an aggregate entry to the cf-tail store |
--concurrency <n> | Maximum apps fetched in parallel (default 4) |
--log-limit <count> | Maximum parsed rows and bounded raw-text size per app |
cf-tail errors
Shortcut for snapshot --level error:
cf-tail errors --region ap10 --org sample-org --space sample --since 1h
cf-tail summary
Aggregate counts for every matching app:
cf-tail summary \
--region ap10 \
--org sample-org \
--space sample \
--json
cf-tail stream
Multiplex live logs for every matching app. By default, the runtime
re-discovers the app list every 30 seconds, picking up newly started apps and
dropping stopped ones. Use --rediscover off (or --rediscover 0s) to disable.
cf-tail stream \
--region ap10 \
--org sample-org \
--space sample \
--include-regex "^api-" \
--rediscover 60s
| Stream-only flag | Description |
|---|---|
--max-lines <count> | Stop after emitting N rows |
--rediscover <duration> | Re-discover the app list at this interval (e.g. 30s, 2m, off) |
--flush-interval-ms <ms> | Batch window before append events are emitted |
--retry-initial-ms <ms> | Initial reconnect delay after unexpected stream exits |
--retry-max-ms <ms> | Maximum reconnect delay |
--log-limit <count> | Maximum parsed rows and bounded raw-text size per app |
--save | Persist bounded redacted stream appends into the cf-logs store |
-q, --quiet | Suppress discovery and stream-state messages on stderr (text mode only) |
cf-tail store path | list | clear
cf-tail store path
cf-tail store list
cf-tail store list --json
cf-tail store clear
cf-tail --version
Prints the installed @saptools/cf-tail semantic version.
📁 Store File
The aggregate cf-tail store lives here:
~/.saptools/cf-tail-store.json
It contains one entry per (apiEndpoint, org, space) with:
fetchedAt,updatedAtappCount,rowCountapps: [{ appName, rowCount, truncated }, ...]
Per-app raw text continues to live in the existing cf-logs store at
~/.saptools/cf-logs-store.json (used when you pass --save). The cf-tail
store is metadata only.
Prefer readTailStore(), persistTailSnapshot(), cf-tail store path, or
cf-tail store list over parsing the file directly.
🔐 Security Notes
- The runtime redacts the current SAP email and password before emitting or
persisting log content. Pass
extraSecrets(programmatic) or--extra-secret <value>(CLI, repeatable) to add custom redaction rules. - Persisted snapshots are bounded and written with file locking plus atomic replace semantics.
- Neither store file is safe for public repositories. Even after redaction, they still reveal app names, org names, spaces, endpoints, and log content.
- If your application logs contain additional secrets beyond SAP credentials, add custom runtime redaction rules before persisting or forwarding output.
❓ FAQ
How is this different from @saptools/cf-logs?
cf-logs is single-app focused: one --app per CLI invocation, one key per
store entry, one redaction set. cf-tail is multi-app: discovery, parallel
snapshot, multiplexed live stream, chronological merge, cross-app filtering,
and an aggregate store. It builds on cf-logs, not against it.
Do I still need cf-logs installed?
cf-tail depends on @saptools/cf-logs automatically. Install
@saptools/cf-tail and you get both.
Does stream automatically pick up new apps?
Yes — every --rediscover interval the runtime re-runs cf apps, computes the
diff, starts streams for new apps, and stops streams for apps that are no
longer started.
How do I scope to a single app?
--apps demo-app (or --include demo-app). Same shape as cf-logs's
single-app commands once you scope down.
🛠️ Development
From the monorepo root:
pnpm install
pnpm --filter @saptools/cf-tail cspell
pnpm --filter @saptools/cf-tail lint
pnpm --filter @saptools/cf-tail typecheck
pnpm --filter @saptools/cf-tail test:unit
pnpm --filter @saptools/cf-tail test:e2e
pnpm --filter @saptools/cf-tail build
pnpm --filter @saptools/cf-tail check
🤝 Author
Maintained by dongtran.
History
Others providing
Compare all 20 on the Logging page →- ABAP-LoggerABAP-LoggerA logging library for ABAP that records messages into the standard Application Log (BC-SRV-BAL) and displays them from there, installed through abapGit on ABAP 702 or higher.independent, abapLogging library for ABAP over the Application Logfrom ABAP
- abap-log-exporterabap-log-exporterExports SAP NetWeaver logs from the Business Application Log to an external log system such as Graylog or Loki, converting entries to GELF or Loki format through a separately configured reader, converter and connector.independent, abapExports Business Application Log entries to Graylog or Lokifrom ABAP
- ABAP-PRCABAP-PRCA framework for custom multi-step ABAP processes: a process class declares the states, and the framework runs each document through them and monitors the run.independent, abapFramework for multi-step ABAP processes with monitoringfrom ABAP
- SAP Application Logging service for SAP BTPSAP Application Logging service for SAP BTPCollects an application's log lines from Cloud Foundry or Kyma into a searchable Kibana, for the retention the plan sets.sap official, btpCollects Cloud Foundry or Kyma logs into a searchable Kibanafrom BTP/BAIP
- SAP Cloud LoggingSAP Cloud LoggingAn instance-based observability service built on OpenSearch that stores and analyses logs, metrics and traces from Cloud Foundry, Kyma, Kubernetes and other runtime environments.sap official, btpOpenSearch-based store for logs, metrics and tracesfrom BTP/BAIP
- com.sap.cds:cds-services-bomcom.sap.cds:cds-services-bomThe Maven bill of materials for CAP Java, pinning every com.sap.cds module in a release, from the API and core runtime to the Spring Boot starters and the CQN engine, to the same version.sap official, capMaven bill of materials pinning CAP Java module versionsfrom CAP
- @cap-js/audit-logging@cap-js/audit-loggingIntegration with the SAP Audit Log service, so operations on personal data are recorded in the form an auditor expects without the application writing the entries.sap official, capCAP integration with the SAP Audit Log servicefrom CAP
- abap-logabap-logA logging library for ABAP with one logger interface in front of several targets, from the Application Log and the job log to database tables, files and the Eclipse console.independent, abapABAP logging library with one interface across output targetsfrom ABAP
- ABAP_LOGGINGABAP_LOGGINGAn object-oriented wrapper around SAP's Business Application Log (BAL) for ABAP NetWeaver, chaining texts, messages and exceptions onto a log header that persists in its own or the same connection.independent, abapObject-oriented wrapper around the Business Application Logfrom ABAP
- abap-cloud-loggerabap-cloud-loggerA logging library for ABAP Cloud that wraps the released class CL_BALI_LOG in a chainable logger, collecting exceptions, messages and tables, with a stopwatch and a sticky context tag.independent, abapChainable logger for ABAP Cloud around CL_BALI_LOGfrom ABAP
- abap-fm-loggerabap-fm-loggerA logger for ABAP function modules (RFC) that stores each call's parameters as JSON in one table, with a viewer report to search the log and reprocess a record, akin to WE10 and WE19.independent, abapLogger storing RFC function module call parameters as JSONfrom ABAP
- openui5-error-collectoropenui5-error-collectorA UI5 library that collects a running app's JavaScript errors, unhandled Promise rejections and UI5 log events, and can post them to a backend with navigator.sendBeacon.independent, ui5UI5 library collecting an app's JavaScript errorsfrom UI5
- open-abap-balopen-abap-balApplication logging for ABAP code transpiled to JavaScript and run on Node.js, one of the runtime libraries open-abap.org lists.community org, abapApplication logging for ABAP transpiled to JavaScript on Node.jsfrom ABAP
- @openui5/sap.ui.core@openui5/sap.ui.coreThe OpenUI5 core: the module loader, the MVC runtime, data binding, routing, theming and the test stack, which is everything a UI5 app does before a single community package is added.sap official, ui5Framework core: module loader, MVC runtime, binding, routing, themingfrom UI5
- abap-fluentdabap-fluentdA Fluentd client written in ABAP for sending log lines from an ABAP system to a Fluentd collector, where entries are flushed with an explicit COMMIT WORK.independent, abapFluentd client in ABAP for sending log lines to a collectorfrom ABAP
- @saptools/cf-logs@saptools/cf-logsA command line and typed Node.js library that fetches and streams the logs of one Cloud Foundry app and parses them into structured rows.independent, btpLog fetcher and parser for one Cloud Foundry appfrom BTP/BAIP
- sap-usi-logging-apisap-usi-logging-apiAn object-oriented encapsulation around SAP's Application Log (transaction SLG1), controlled by customizing, with attachable data containers that SLG1 shows behind a detail button.independent, abapObject-oriented wrapper around SAP's Application Log (SLG1)from ABAP
- srbjsloggersrbjsloggerA browser JavaScript logger whose log, warn and error calls write prominent output to the console, loaded into a UI5 app through index.html or the manifest's resources.independent, ui5A browser JavaScript logger whose log, warn and error calls write prominent output to the console, loaded into a UI5 app through index.html or the manifest's resources.from UI5
- abap-message-loggerabap-message-loggerA message logger for ABAP Cloud that collects T100 messages, BAPIRET2 structures, exceptions and plain text before saving them to the Application Log.independent, abapMessage logger for ABAP Cloud that saves to the Application Logfrom ABAP
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
History in the atlas
- First seen.
For your agent
- Ref
artifact:saptools-cf-tail- JSON
- /artifacts/saptools-cf-tail.json
- MCP
- Connecting an agent