> For the complete documentation index, see [llms.txt](https://docs.datasentinel.io/manual/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.datasentinel.io/manual/guides/readme/pdf-reports.md).

# Generate, Email, and Schedule PDF Reports

<div data-with-frame="true"><figure><img src="/files/5005n8wCBUsqlOL8SaiY" alt="Generate, Email, and Schedule PDF Reports"><figcaption></figcaption></figure></div>

Datasentinel can export the dashboards you already use as **PDF reports**: same graphs, same tables, same tag and time-window scope, packaged as a single file you can download, email, or schedule on a recurring basis. The feature is available from every dashboard and through the [**Reporting API**](/manual/implementation/platform-usage/api-reference/reporting.md), so the same operations work from the UI or from a script.

This guide focuses on **why reports are worth using as a routine practice**, then walks through generating, emailing, and scheduling them, and finishes with concrete comparison recipes.

{% hint style="info" %}
Reports inherit the filters and time window of the screen you launch them from, unless you are creating a **scheduled** report (which uses its own window). See [**Reporting**](/manual/features/key-features/reporting.md) for the full feature reference.
{% endhint %}

## Why PDF reports change the storage math

Datasentinel stores metrics in InfluxDB on the platform host. The default sizing assumes **14 days of retention**, and the [**recommended disk size**](/manual/getting-started/installation/platform.md) scales with both the number of monitored instances and the retention period. Extending retention from 14 days to a year is a 26× increase in time, which means a roughly 26× increase in metric storage (the actual factor depends on activity volume, but the trend is linear).

**PDF reports break that trade-off.** A weekly Full Report is at most a few megabytes, and a year of weekly snapshots is therefore a handful of dozens of files: trivial to keep on a wiki, a SharePoint folder, an S3 bucket, or attached to a ticket.

<table><thead><tr><th width="220">Approach</th><th>What you keep</th><th>Cost profile</th></tr></thead><tbody><tr><td><strong>Extend metric retention</strong></td><td>Every sample, queryable at full resolution.</td><td>Storage scales linearly with retention <em>and</em> instance count. Backups, dispatcher load, and platform sizing all grow with it.</td></tr><tr><td><strong>Archive PDF reports</strong></td><td>A snapshot of the period: dashboards, top-N tables, plans, summaries.</td><td>A few MB per report, independent of how many instances you monitor. Lives outside the platform, so it survives upgrades, restores, and platform decommissions.</td></tr></tbody></table>

{% hint style="info" %}
Reports are not a replacement for live dashboards or for the [**Workload API**](/manual/implementation/platform-usage/api-reference/workload.md) (which returns raw metrics in JSON or CSV). They are a way to preserve **the analytical view** of a workload long after the underlying samples have been rolled off.
{% endhint %}

## Why PDF reports unlock comparison

Once two reports of the same shape exist, comparing them is a tab-switching exercise that anyone can do, regardless of whether they have a Datasentinel account.

Three patterns come up most often:

* **Before / after a change**: generate a Full Report for the week preceding a migration, an index addition, or a PostgreSQL upgrade, then a second one for the week after. The pair tells you whether the change actually moved the needle.
* **Week-over-week or month-over-month**: a recurring scheduled report gives you a stack of identically-shaped PDFs. Drift in top queries, table sizes, or system metrics jumps out.
* **Same window, two scopes**: generate one report filtered on `application=A` and one on `application=B` for the same time range. Side-by-side reveals which workload is heavier, where the wait events differ, which queries dominate each side.

{% hint style="info" %}
Reports always carry their **time window**, **tag filters**, and **database scope** in the header. This is what makes them unambiguous to compare: there is no doubt about which slice of data each PDF reflects.
{% endhint %}

***

## Before you start

<table><thead><tr><th width="220">Requirement</th><th>Detail</th></tr></thead><tbody><tr><td><strong>SMTP configured</strong></td><td>Mandatory for the <strong>Email</strong> and <strong>Scheduled email</strong> modes. Not needed for one-off downloads. See <a href="/spaces/lcWi6G1jtNuyGT9C0pkc/pages/P5q1u8YR9Q06lDGm8SWO"><strong>SMTP configuration</strong></a>.</td></tr><tr><td><strong>A tagging strategy</strong></td><td>Reports are scoped through tag filters. A consistent tagging scheme makes per-application, per-environment, or per-cluster reports trivial. See <a href="/pages/jdy0zIUnjZHb9XwBGH0Y"><strong>Organize Content using Tags</strong></a>.</td></tr><tr><td><strong>Access token (API only)</strong></td><td>For Reporting API calls. Tokens are valid 24 h. See <a href="/pages/lk2kg8QxwAUbloVoBKDz"><strong>Automate with the API</strong></a>.</td></tr></tbody></table>

## What you can report on

Datasentinel ships one **Full Report** that bundles every section, plus seven individual reports for users who want one specific angle:

<table><thead><tr><th width="200">Report</th><th>Endpoint</th><th>What it contains</th></tr></thead><tbody><tr><td><strong>Full</strong></td><td><code>full-report</code></td><td>All sections below in a single PDF. The default choice for an archive snapshot.</td></tr><tr><td><strong>Session History</strong></td><td><code>session-history-report</code></td><td>Active Session History samples, grouped by wait-event type and an optional secondary tag dimension.</td></tr><tr><td><strong>Top Queries</strong></td><td><code>top-queries-report</code></td><td>The most resource-intensive queries for the window, ranked by the dimension you pick (total time, calls, blocks read/written, WAL bytes, etc.).</td></tr><tr><td><strong>Top Tables</strong></td><td><code>table-report</code></td><td>Heaviest tables and indexes with their access patterns and sizes.</td></tr><tr><td><strong>Instance</strong></td><td><code>instance-report</code></td><td>Per-cluster metrics: connections, transactions, WAL, replication, configuration.</td></tr><tr><td><strong>Server</strong></td><td><code>server-report</code></td><td>Host-level metrics (CPU, memory, I/O, network) when collected.</td></tr><tr><td><strong>Query</strong></td><td><code>query-report</code></td><td>Deep-dive on one specific query identified by its <code>query_md5_id</code>.</td></tr><tr><td><strong>Data Size</strong></td><td><code>data-size-report</code></td><td>Table and index sizes, useful for capacity-planning archives.</td></tr></tbody></table>

***

## Generate a report

{% tabs %}
{% tab title="From the UI" %}
Every dashboard exposes a **reporting icon** in the top-right toolbar.

1. Open the dashboard you want a report for, set the filters and time window you need, and click the reporting icon.
2. Pick the **report type**. From a generic page (such as Home) you can choose any of the eight types; from a specific dashboard (such as Session History) only the matching type is available.
3. Optionally restrict to **a single database** (default: All).
4. Choose the **delivery mode** in the dialog:
   * **Download**: the PDF generates and downloads to your browser immediately.
   * **Email**: enter recipients and an optional subject, then send. Requires SMTP.
   * **Scheduled email**: covered in the next section.

The filters and time window from the current screen are carried into the report, so the PDF reflects exactly what you were looking at.
{% endtab %}

{% tab title="From the API" %}
The same operation as a one-liner. Each report type has its own endpoint under `/ds-api/activity/`; the body shape is the same for all of them: a time window, optional tag filters, optional database, plus type-specific knobs (such as the `by` ranking dimension for Top Queries).

```bash
cat > /tmp/report.json <<EOF
{
  "from": "2026-05-19",
  "to":   "2026-05-26",
  "filters": [ { "tag": "environment", "value": "production" } ],
  "database": "All"
}
EOF

curl -sk \
  --header "user-token: $ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  -X POST https://$DATASENTINEL_HOST/ds-api/activity/full-report \
  -d @/tmp/report.json \
  --output full-report-2026-05-19_2026-05-26.pdf
```

To **email** the report directly instead of downloading it, add three fields:

```json
{
  "from": "2026-05-19",
  "to":   "2026-05-26",
  "filters": [ { "tag": "environment", "value": "production" } ],
  "report_type": "email",
  "subject":     "[Datasentinel] Weekly production digest",
  "recipients":  ["dba-team@company.com", "platform-owners@company.com"]
}
```

Swap `full-report` for any of the seven individual endpoints to scope the output. The full list lives in the [**Reporting API reference**](/manual/implementation/platform-usage/api-reference/reporting.md).
{% endtab %}
{% endtabs %}

***

## Schedule recurring reports

A scheduled report is the cheapest way to build a long-term archive. It runs unattended on a cadence you choose and lands in the recipients' inbox each time.

{% stepper %}
{% step %}

### Configure SMTP first

Email and scheduled email both go through SMTP. If you haven't set this up yet, follow [**SMTP configuration**](/manual/implementation/platform-usage/configuration/smtp.md) and run a **Test e-mail** to confirm delivery.
{% endstep %}

{% step %}

### Create the scheduled report

From any dashboard, open the reporting dialog and pick **Scheduled email**. Configure:

* **Frequency**: daily or weekly.
* **Day and hour** the report should run.
* **Recipients** and optional subject.
* The **activity time range** the report should cover (this is the rolling window each scheduled run will recompute against).

{% hint style="info" %}
The report actually starts **3 minutes after** the scheduled time so the most recent samples are included in the run.
{% endhint %}
{% endstep %}

{% step %}

### Manage and audit

The **Reporting** screen lists every scheduled job. You can change properties, delete a job, and open any entry to view its execution history (status and duration of every past run).

{% hint style="info" %}
An administrator sees every scheduled report across all users. A non-administrator can only see and manage their own.
{% endhint %}
{% endstep %}
{% endstepper %}

***

## Comparison recipes

### Before / after a change

Use a Full Report bracketing the change. Same scope, same window length, two adjacent time ranges.

```bash
# Before. The week leading up to the change.
curl -sk --header "user-token: $ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  -X POST https://$DATASENTINEL_HOST/ds-api/activity/full-report \
  -d '{ "from": "2026-05-12", "to": "2026-05-18",
        "filters": [{"tag":"application","value":"sales"}] }' \
  --output sales-before-index.pdf

# After. The week following the change.
curl -sk --header "user-token: $ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  -X POST https://$DATASENTINEL_HOST/ds-api/activity/full-report \
  -d '{ "from": "2026-05-20", "to": "2026-05-26",
        "filters": [{"tag":"application","value":"sales"}] }' \
  --output sales-after-index.pdf
```

Open both PDFs side by side. Top Queries, wait events, I/O metrics, and table activity should all shift in the expected direction if the change worked.

### Week-over-week digest

Schedule a weekly Full Report and archive the inbox. After three months you have a 13-PDF time series; after a year you have 52. Each PDF is self-describing (header carries window + filters), so the archive can outlive the platform that produced it.

### Two scopes at the same time

When two applications share a platform, generate the same report twice with different tag filters to compare workloads directly.

```bash
curl -sk --header "user-token: $ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  -X POST https://$DATASENTINEL_HOST/ds-api/activity/top-queries-report \
  -d '{ "from": "2026-05-19", "to": "2026-05-26",
        "filters": [{"tag":"application","value":"sales"}],
        "by": "total_time" }' \
  --output sales-top-queries.pdf

curl -sk --header "user-token: $ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  -X POST https://$DATASENTINEL_HOST/ds-api/activity/top-queries-report \
  -d '{ "from": "2026-05-19", "to": "2026-05-26",
        "filters": [{"tag":"application","value":"billing"}],
        "by": "total_time" }' \
  --output billing-top-queries.pdf
```

The same recipe works for primary vs replica, production vs staging, or any two slices that share a tag dimension.

***

## Best practices

* **Pick the Full Report for archives, the per-section reports for sharing**: one PDF is easier to file; a single section is easier to read with one stakeholder.
* **Standardize the window**: pick a cadence (weekly or monthly) and keep it. Comparable archives are the ones that share the same window length and tag scope.
* **Name files predictably**: when scripting via API, write filenames like `<scope>-<from>_<to>-<type>.pdf` so an archive of hundreds remains scannable.
* **Don't pair reports with extended retention by reflex**: in most cases, 14 days of live metrics plus a year of weekly PDFs is cheaper and more useful than 90 days of live metrics on their own.

## Where to go next

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h4><i class="fa-code" style="color:$primary;">:code:</i></h4></td><td><strong>Automate with the API</strong>: drive the Reporting API end-to-end, alongside the other Platform-API recipes.</td><td><a href="/pages/lk2kg8QxwAUbloVoBKDz">/pages/lk2kg8QxwAUbloVoBKDz</a></td></tr><tr><td><h4><i class="fa-tag" style="color:$primary;">:tag:</i></h4></td><td><strong>Organize Content using Tags</strong>: design the tags that drive report scoping and comparison.</td><td><a href="/pages/jdy0zIUnjZHb9XwBGH0Y">/pages/jdy0zIUnjZHb9XwBGH0Y</a></td></tr><tr><td><h4><i class="fa-server" style="color:$primary;">:server:</i></h4></td><td><strong>Install On-Premises and Configure Agentless Connections</strong>: where SMTP is configured and where the Reporting feature lives.</td><td><a href="/pages/MjcfkDxCRebodLCSX0X7">/pages/MjcfkDxCRebodLCSX0X7</a></td></tr><tr><td><h4><i class="fa-rocket" style="color:$primary;">:rocket:</i></h4></td><td><strong>Onboard Your First PostgreSQL Cluster</strong>: get an instance under monitoring so it has data worth reporting on.</td><td><a href="/pages/A9sFriZivMT20vNkYp0w">/pages/A9sFriZivMT20vNkYp0w</a></td></tr></tbody></table>

## Conclusion

PDF reports turn Datasentinel into a system of record, not just a live dashboard. They cost almost nothing to store, they outlive the metrics they were generated from, and they make comparisons (before/after, week-over-week, scope-against-scope) a matter of opening two files. Use them as the routine alternative to extending metric retention, and as the standard artefact for any change you want to evidence.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.datasentinel.io/manual/guides/readme/pdf-reports.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
