drupal / ai_recipe_observability_views
Store AI provider events in SQL and provide searchable logs and usage charts through Views.
Package info
git.drupalcode.org/project/ai_recipe_observability_views.git
Type:drupal-recipe
pkg:composer/drupal/ai_recipe_observability_views
Requires
- drupal/ai: ^1.4.8
- drupal/charts: ^5.2.3
- drupal/core: ^11.4
- drupal/logger: ^1.0.0-alpha6
- drupal/logger_db: ^1.0.0-alpha4
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-08 16:39:51 UTC
README
AI observability with Views is a Drupal recipe that stores Drupal AI provider
events in your SQL database and gives you a searchable event log, four usage
charts, a guardrail results report and a thread view, all built as editable
Views under /admin/reports/ai-requests.
After applying, the Reports menu gains an AI requests entry with a
paginated event log, an event detail page showing the captured prompt and
response, and bar charts for requests per day, requests per model, tokens per
model and tokens per day. Every page is a Views display you can change at
/admin/structure/views.
Features
- Event log: one row per provider lifecycle event (request started, response received, streaming response received, provider disabled) with filters for UTC date prefix, provider, model, operation, user ID, event name and request ID. The request ID links the start and completion events of a single call.
- Event detail: time, provider, model, operation, user, reported tokens, request ID, the captured prompt and response text, provider configuration, tags and the token usage breakdown (input, output, reasoning, cached).
- AI request volume: requests started per UTC day.
- AI requests by model: requests started per provider and model.
- AI tokens by model: reported total tokens per provider and model.
- AI token trend: reported total tokens per UTC day.
- Data tables under every chart: the numbers behind each chart are rendered as a table, so the reports work without JavaScript and with screen readers.
- Shared filters on charts: date prefix, provider, model and operation filters narrow every chart.
- Plain SQL storage: events are written by the AI Observability submodule through Logger and Logger DB. No external service, agent or OpenTelemetry collector is required.
Reports
All paths start at /admin/reports/ai-requests:
| Suffix | Report |
|---|---|
| (none) | Paginated event log with date prefix, provider, model, operation, user, event name and request ID filters |
/event/{uuid} | Individual event, including captured prompt/response and metadata |
/volume | Requests started per UTC day |
/models | Requests started per provider/model |
/tokens | Reported total tokens per provider/model |
/token-trend | Reported total tokens per UTC day |
/guardrails | Events where a guardrail ran, with each guardrail's result and message |
/conversation?thread=<request ID> | Every event in one request thread, in time order, with prompts and responses. Also available as a block |
The event log is the default menu tab; the four charts and the guardrail report are menu tabs under the
same report. The conversation page has no tab; reach it from a request ID link. The event display uses the Views path
admin/reports/ai-requests/events; Views serves its default tab at
/admin/reports/ai-requests. The parent Reports link is supplied as menu-link
content because Drupal 11.4.6 does not generate it from the default tab settings.
Screenshots
Event log:

Event detail:

AI request volume:

AI requests by model:

AI tokens by model:

AI token trend:

Guardrail results
Guardrails run inside the AI module before and after a provider call. Their
results are not written as separate log messages; they are stored in the
metadata.guardrails array of the request-start event (and, for post-generate
guardrails, the response event). The AI guardrails report lists only events
where that array has content, so passed, stopped and rewritten checks are
separated from the ordinary event stream.
- A request stopped by a guardrail never reaches the provider, so it appears as
a request-start event only, with a
StopResult. - The Result filter narrows to stopped, rewritten-prompt, rewritten-response or passed checks.
- Guardrail results are only recorded when prompt logging (
log_input) is on, because the AI Observability logger reads them from the input payload. - Rows from other channels are guardrail warnings written by other modules. AI Automators logs one when a run is blocked; the core guardrail subscriber does not log anything itself.
The event detail page also shows the raw guardrail results for one event.
Following a thread
Each provider call gets a request ID (metadata.provider_request_id). A call
made on behalf of another, such as a tool call or sub-agent call, records the
caller's ID as metadata.provider_request_parent_id. The AI conversation
report takes a request ID and lists that request and every child that names it
as parent, oldest first, with the prompt on request-start events and the
response on completion events.
- Request IDs in the event list and the detail page link straight to the conversation for that thread.
- Only one level is followed. A grandchild names the child as its parent, so open the child's ID (linked in each entry) to go deeper.
- The same view is available as the AI conversation block. Place it on any
page; it reads the request ID from the
threadquery parameter or from its own exposed field. - The AI Assistant thread ID used by the chatbot is not part of the logged metadata in AI 1.4.8, so threads are followed by provider request ID.
How counting works
The log lists events, not requests. Request charts count only request-start
events (ai.pre_generate_response). Token charts sum the total token usage
reported on completion and streaming completion events
(ai.post_generate_response and ai.post_streaming_response). If a provider
emits multiple completion events for a call, their values are summed; the
recipe does not deduplicate provider events. Missing usage is left out rather
than estimated as zero. Day buckets use UTC and days without events are
omitted. Provider-disabled events never count as requests.
Coverage is limited to calls that go through the Drupal AI provider layer. Calls made directly through a vendor SDK are invisible. Failed or abandoned calls can leave a start event without a completion. The recipe does not report latency, error rates or monetary cost, because the AI Observability module does not record that data. Aggregate reports query all retained records, so use the date-prefix filter on large databases.
Requirements and access
- AI 1.4.8 or later, with its AI Observability submodule, plus a configured AI provider to produce events. The recipe does not configure credentials, choose a model or make paid requests.
- Logger 1.0.0-alpha6 or later and Logger DB 1.0.0-alpha4 or later. Both are alpha releases and are not covered by the Drupal security advisory policy.
- Charts 5.2.3 or later with its bundled Chart.js integration.
- Drupal 11.4 or later. Logger DB alpha4 was tested with the legacy
mysqldatabase driver name and does not yet support Drupal 11.4's namespaced driver identifier; see VALIDATION.md.
All supplied Views require Administer AI Observability. No role is granted this permission automatically. General Logger DB tools, if separately enabled, use their own permissions; review access to those tools too.
Installation
Download the recipe and its dependencies with Composer from your project root:
composer require drupal/ai_recipe_observability_views
Rebuild caches so Drupal discovers the new modules, then apply the recipe:
drush cache:rebuild
php vendor/bin/dr recipe:apply recipes/ai_recipe_observability_views
drush cache:rebuild
Back up the database before applying. A failed application can leave partial changes, and restoring the database does not undo Composer or filesystem changes.
Apply in DDEV
After approving module installation, from the project root:
ddev composer require 'drupal/logger:^1.0.0-alpha6' 'drupal/logger_db:^1.0.0-alpha4' 'drupal/charts:^5.2.3'
ddev drush cache:rebuild
AI is already required here; on another site also require drupal/ai:^1.4.8.
Composer downloads dependencies; the recipe enables them.
Take a uniquely named database backup outside the web root, verify it, and keep its exact path for recovery. Create a private, ignored backup directory first and use a new filename for every attempt:
ddev export-db --database=db --file=.ddev/.recipe-backups/ai-observability-baseline.sql.gz
ddev exec gzip -t .ddev/.recipe-backups/ai-observability-baseline.sql.gz
ddev exec php vendor/bin/dr recipe:info /var/www/html/recipes/ai_recipe_observability_views
ddev exec php vendor/bin/dr recipe:apply /var/www/html/recipes/ai_recipe_observability_views -v
ddev drush cache:rebuild
Never overwrite an earlier baseline. recipe:info checks prerequisites; it is
not a dry run. Restore the recorded baseline before a clean retry, preserving
any newer work first.
Recipe inputs
Prompt and response text capture are on by default. To keep request metadata
but skip the text, pass the two inputs as 0:
ddev exec php vendor/bin/dr recipe:apply /var/www/html/recipes/ai_recipe_observability_views --input='ai_recipe_observability_views.log_input=0' --input='ai_recipe_observability_views.log_output=0'
The installed CLI accepts boolean inputs as 1 or 0, not the strings true
or false. You can change text capture later in the AI Observability settings.
The AI module may summarize or truncate large payloads. Logs can contain
prompts, responses and provider configuration.
Updating a site that already applied this recipe
A recipe compares the config it ships with what is already on the site and refuses to apply when they differ, so re-running the recipe after this package changed does not update the Views. Import the changed Views directly:
ddev drush config:import --partial --source=/var/www/html/recipes/ai_recipe_observability_views/config -y
ddev drush cache:rebuild
This overwrites any edits made to those Views in the UI.
Configuration effects
- Enables AI Observability logging for all four supported lifecycle events and removes the tag restriction. Disables fallback message formatting because Logger supports structured placeholders.
- Sets Logger output to the database only, down to the info level. This replaces the existing target list and affects every Drupal logging channel, not only AI. Re-add file or syslog targets afterwards if you need them.
- Replaces Logger's selected field list with service name, UUID, time, timestamp, channel, severity, raw message, request URI, user ID, metadata and exception. Undefined context fields are stored too; zero and empty values are retained.
- Adds five Views, one AI requests Reports menu link and the chart tabs.
- Keeps Logger DB retention settings; a fresh installation defaults to 93 days with cron cleanup. Configure retention according to the site's needs.
- Leaves providers, credentials, role permissions, OpenTelemetry settings and the site's default Charts configuration untouched. Chart.js loads through Charts library discovery with a CDN fallback; follow the Charts documentation to install the JavaScript library locally when CDN use is unwanted.
Tool-use reporting
The installed AI 1.4.8 text logger omits structured tool-call objects. Enabling input/output capture does not provide a reliable executed-tool list or usage count. Such reports need structured tool execution records first; the AI Agents progress API exposes tool-started and tool-finished events. Tool-use reports are not part of this recipe.
Related modules
Other modules that record or expose AI requests and token usage:
Validation
See VALIDATION.md for checks and remaining validation. Runtime checks should cover empty reports, normal and streaming completions, chart totals compared with stored events, filters, detail links, anonymous and unprivileged access, keyboard operation and narrow-screen rendering. Apply twice to verify repeatability and restore temporary test data afterward.
Sources
- Drupal AI: AI Observability is a submodule.
- Logger
- Logger DB
- Charts
- Drupal recipes