Skip to main content

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​

FieldWhenWhat it is
eventalwaysexternal_call
componentalwaysthe 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
sourcewhen the call is for a context streamthe source's name as registered. Absent for calls that belong to no source, such as the app calling the agent runner
streamfor an ingest walkthe stream being walked
datasetfor a questionthe dataset the question was compiled against
kindalwayshttp or sql
methodhttpthe HTTP method
targetalwaysfor 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_segmentshttphow many segments the full path had, so calls to different depths of one API can still be told apart
enginesqlpostgres or oracle
operationsqlthe statement's first word (SELECT), CONNECT for opening a session, or PROBE for the Test button
fingerprintsql statementsa 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
statusalwaysfor 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
rowssql statementsrows returned
byteshttpthe response body size, when known
duration_msalwayswall-clock time of the call
atalwayswhen 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 target close 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.