The external-call log
Prism writes one line to its containers' standard output for every call it makes to a system outside itself: every HTTP request, and every statement it runs against a source database. Collect pod logs the way you collect any other container's, and a team that owns a source (GitHub, GitLab, Jira, an Oracle or Postgres database) can answer "was that load from Prism, when, and how much?" from their own tooling.
It is on by default. externalCallLog.enabled: false in your values turns it
off in every container (install parameters).
What a line looks like
Each line is one JSON object on its own line:
{"event": "external_call", "component": "prism-ingest", "source": "gitlab",
"stream": "merge_requests", "kind": "http", "method": "GET",
"target": "gitlab.example.com/api/…?page=&per_page=", "path_segments": 6,
"status": 200, "bytes": 18234, "duration_ms": 412,
"at": "2026-09-19T10:02:03.412+00:00"}
{"event": "external_call", "component": "prism-ingest", "source": "clarity",
"stream": "allocations", "kind": "sql", "engine": "oracle",
"target": "clarity-db.example.com:1521/CLARITY", "operation": "SELECT",
"fingerprint": "3f9a1c0e22b7", "status": "ok", "rows": 48213,
"duration_ms": 9120, "at": "2026-09-19T10:03:11.020+00:00"}
To find them, search your collector for "event": "external_call", or for
event=external_call if it parses JSON fields.
The fields
| Field | When | What it is |
|---|---|---|
event | always | external_call |
component | always | the container that made the call: prism-app, prism-ingest, semantic-mcp, management-mcp, or prism-app-selftest for the self test run from inside the app pod |
source | when the call is for a context stream | the source's name as registered. Absent for calls that belong to no source, such as the app calling the agent runner |
stream | for an ingest walk | the stream being walked |
dataset | for a question | the dataset the question was compiled against |
kind | always | http or sql |
method | http | the HTTP method |
target | always | for http, the host and port, the first path segment only (as {…} unless it is a common constant word such as api), and the query-string parameter names with every value removed. The rest of the path is replaced by …, because a path can carry a person's login or a private repository's name; where Prism knows the path's pattern it writes that instead (api.github.com/users/{login}). For sql, the host, port and database or Oracle service name, or dsn for an Oracle connect descriptor |
path_segments | http | how many segments the full path had, so calls to different depths of one API can still be told apart |
engine | sql | postgres or oracle |
operation | sql | the statement's first word (SELECT), CONNECT for opening a session, or PROBE for the Test button |
fingerprint | sql statements | a short hash of the statement with its literal values removed, so repeated runs of the same query can be grouped. The statement text itself is never written |
status | always | for http, the response status code, or the error type (ConnectTimeout, ConnectError) when no response came back. For sql, ok, the database's own code (ORA-01017, a Postgres SQLSTATE such as 57014), or the error type |
rows | sql statements | rows returned |
bytes | http | the response body size, when known |
duration_ms | always | wall-clock time of the call |
at | always | when the line was written, in UTC |
What is never in a line
No credential, token, password or header. No query-string value, so a key
passed as ?api_key= appears as ?api_key=, and a query item with no =,
which may itself be a secret, appears only as …. No path beyond its first
segment. No user name or password from a URL, or from a database host that
has one written into it. No request or response body, no SQL statement text, no bind value and no
row data. An error is reported by its code or type, never its message, because
a database's error message can quote a value.
Which calls are covered
- Every HTTP request made by the app, the ingest jobs and tick, the semantic query MCP, the management MCP and Stream setup's discovery service. This covers every ingest walk (manifest engine and the GitHub, Jira, GitLab and spend lanes), the Test button, the self test, Snowflake (whose SQL runs over HTTP), the Agent Router management API, the app's calls to the agent runner and its own MCP servers, and a Stream setup session's reads of your API and its description. The hook is installed once per container, when it starts, so a call site added later is covered without anyone remembering to add it.
- Every statement against a source database: the ingest walk's Postgres and Oracle sessions and statements, the semantic query MCP's Oracle statements, a Stream setup session's Postgres and Oracle statements, and the Test button's Postgres and Oracle probes. A Test that was refused before any connection was attempted writes no line, because nothing left the pod.
Known gaps
- The agent runner is a separate program. Its calls to the Agent Router for inference are not written by this log. The Agent Router records them itself.
- The live GitHub tools (
github-live-mcp) call GitHub through GitHub's own MCP server, a separate program the container runs. Those calls are not written by this log. - Prism's own database is inside your installation, not an external system, so statements against it are not logged.
- Retries each write their own line, and nothing numbers them. A retry
storm shows as many lines for the same
targetclose together. - The first path segment is written only when it is a common constant
API word (
api,rest,graphql,repos,users,v4, and a few more). Any other first segment is written as{…}, because a source's document can start its path with a value that names a person. Calls to an API whose first segment is a constant word not on that list therefore read{…}too. - Redirects that Prism's HTTP client follows are one line, for the first request's target, with the final response's status. The intermediate hops are not written.
Which stream
All four containers write these lines to standard output. The one
exception is the self test run from a shell inside the app pod
(python -m prism_app.selftest), which writes them to standard error so that
its report on standard output stays a single JSON document. Most of Prism's
other diagnostics go to standard error. Pod logs carry both, so a collector
that gathers pod logs sees both. If yours separates the two streams, search
standard output for these lines.