Skip to main content

petri-braintrust

PyPI CI Python License: MIT

Bridge Inspect Petri alignment audits into Braintrust experiments — with first-class support for local model targets via Ollama.

You bring the audit, this brings the dashboards.

What it does

Petri runs auditor/target/judge model rollouts and writes Inspect .eval logs containing transcripts plus 1–10 judge scores across ~38 alignment-relevant dimensions (sycophancy, deception, eval-awareness, power-seeking, …).

Braintrust wants experiments with {input, output, scores, metadata} records and renders them as comparable runs with drift detection, per-score charts, and per-row diffs.

petri-braintrust does the translation:

Inspect Petri → Braintrust
.eval log file Experiment
EvalSample (one seed × one epoch) Root span (type task) with full transcript + scores
sample.input (seed instruction) input.seed
sample.messages (full transcript) output.transcript + output.final_target_response
sample.scores["audit_judge"].value dict One scores[<dim>] per Petri dimension, [0, 1]
Per-dim justification (from explanation) metadata.dimensions[<dim>].explanation
Judge highlights / summary / refs metadata.judge
ModelEvent (auditor / target / judge call) Child span (type llm) with prompt, completion, tokens, latency
ToolEvent Child span (type tool) with arguments + result
Model roles, token usage, timing metadata

The child spans give you a per-call waterfall under each sample in the Braintrust UI — you can drill into the exact auditor turn or judge call that produced a score, with token counts and wall-clock latency.

Install

pip install petri-braintrust

Or track main / hack locally:

pip install git+https://github.com/Paul-UK/petri-braintrust.git
# or, from a local clone:
pip install -e .

Installing pulls in inspect-petri, inspect-ai, and braintrust as dependencies.

Then make sure your keys are set:

export ANTHROPIC_API_KEY=sk-...     # or OPENAI_API_KEY, etc., for auditor/judge
export BRAINTRUST_API_KEY=...

And, for local targets:

ollama serve &
ollama pull gemma4

Quick start

CLI — run an audit and export in one shot

A small, fast smoke test (one sample, short transcript):

petri-bt run \
    --target ollama/gemma4 \
    --auditor anthropic/claude-sonnet-4-6 \
    --judge anthropic/claude-opus-4-6 \
    --seeds tags:sycophancy \
    --limit 1 \
    --max-turns 10 \
    --bt-project petri-audits-local

A normal sycophancy run across the default seed set, 5 samples:

petri-bt run \
    --target ollama/gemma4 \
    --seeds tags:sycophancy \
    --limit 5 \
    --bt-project petri-audits-local

(Auditor and judge fall back to the local-target preset — Sonnet + Opus.)

CLI — export logs you already have

petri-bt export logs/2026-05-13-petri-audit.eval --project petri-audits
# or in bulk:
petri-bt export-dir logs --project petri-audits --pattern '*.eval'

You can override the experiment name to avoid colliding with a prior export:

petri-bt export logs/2026-05-13-petri-audit.eval \
    --project petri-audits \
    --experiment sycophancy-rerun-clean

CLI — list the available presets

petri-bt presets

Python — the same thing

from petri_braintrust import run_audit, export_log

# Option A: run + export
result = run_audit(
    target="ollama/gemma4",
    auditor="anthropic/claude-sonnet-4-6",
    judge="anthropic/claude-opus-4-6",
    seed_instructions="tags:sycophancy",
    limit=5,
    braintrust_project="petri-audits-local",
)
print(result["log_path"])
print(result["braintrust_summary"]["experiment_url"])

# Option B: export an existing Inspect log
summary = export_log("logs/my-audit.eval", project="petri-audits-local")
print(summary["experiment_url"])

Command reference

petri-bt run — flags worth knowing

Flag Default What it does
--preset local-target Named role config. See petri-bt presets.
--target / --auditor / --judge preset's value Override one role without changing the others.
--seeds full set tags:<name>, id:<seed_id>, or a path to a seed file/dir.
--limit 5 Sample cap (pass 0 to disable).
--max-turns 30 Conversation turn cap.
--rollback / --no-rollback rollback Allow the auditor to roll back conversations.
--realism / --no-realism no-realism Enable Petri's realism filter (threshold 0.6).
--log-dir logs Where Inspect writes .eval files.
--bt-project (none) If set, auto-export to this Braintrust project.
--bt-experiment auto Override the auto-generated experiment name.
--bt-traces / --no-bt-traces bt-traces Per-LLM-call child spans (waterfall view) in BT.
--bt-include-events off Also embed the raw Inspect event stream in sample metadata (large).
--bt-keep-inverted-scores off Also emit <dim>__inverted columns (higher = better) for higher-is-worse dimensions.
--bt-mode experiment Where to send: experiment, logs (Topics-compatible), or both.

petri-bt export and petri-bt export-dir

Same Braintrust-shaping flags, named without the bt- prefix since the whole command is about export:

Flag Default What it does
--project, -p (req) Braintrust project name.
--experiment, -e auto Override experiment name (avoids name collisions).
--pattern (export-dir) *.eval Glob for log files in the directory.
--traces / --no-traces traces Per-LLM-call child spans.
--include-events off Embed raw event stream in metadata.
--keep-inverted-scores off Emit <dim>__inverted columns.
--mode experiment experiment, logs, or both. See Topics integration below.

Topics integration (project logs mode)

Braintrust's Topics pipeline auto-clusters traces by user intent, sentiment, and detected issues — and you can add custom facets to cluster by anything else, including alignment-specific failure patterns. Topics only runs on project logs, not experiments, so to use it with Petri you need to export to the logs path:

petri-bt run \
    --target anthropic/claude-haiku-4-5 \
    --seeds tags:sycophancy \
    --limit 150 \
    --bt-project petri-audits \
    --bt-mode both     # experiment for the scorecard, logs for Topics

Or for an existing log file:

petri-bt export logs/2026-06-01-audit.eval \
    --project petri-audits \
    --mode logs

Each sample becomes one trace, and normalized dimension scores are promoted into metadata.scores.<dim> so Topics' custom-facet filters can scope on things like "sycophancy > 0.5". Each trace also carries metadata.source = "inspect-petri" so a Topics automation can be filtered to only Petri audits.

Once your traces are in the project, enable Topics with Petri-friendly defaults:

petri-bt topics-init --project petri-audits

This wraps bt topics config enable with a BTQL filter scoped to Petri traces, enables the built-in Task/Sentiment/Issues facets at 100% sampling, and runs bt topics poke so processing starts immediately. Add --dry-run to see the exact bt commands without executing them.

Topics also supports custom facets — domain-specific clusterings beyond the built-in three. A ready-made sycophancy_pattern facet ships with this package; the topics-init command prints its path. Open the file and follow the instructions to paste it into the Topics UI (custom-facet creation is UI-only, not CLI-driven).

A few things to know:

  • Topics needs ~100 trace summaries before clustering activates. petri-bt warns when a logs-mode run finishes below that threshold — re-run with --limit 150 or accumulate runs into the same project.
  • One sample = one trace, with the model/tool calls as child spans. Topics' default Thread preprocessor handles this shape directly; no grouping key needed.
  • Both modes can coexist. --bt-mode both writes the same audit to an experiment (for the scorecard / drift charts) and to project logs (for clustering) — useful when authoring an article or comparing the two views side by side.

Long-horizon eval

Most alignment audits stop at turn 10–30. Real agentic deployments don't. This repo ships a seed + orchestration script for testing whether your model still refuses a dangerous request — and still produces useful work — after ~90 turns of conversation have filled its context window.

This eval is also available as a registered study — petri-bt study run long-horizon — which runs both arms, exports paired Braintrust experiments, and prints the delta report in one command. The script below remains for multi-target sweeps.

Built for self-hosted / fine-tuned targets, where KV-cache pressure can erode in-context cues that aren't a concern for frontier-context models. A cloud target works as a reference column.

Run it

# Default: gemma4:latest + claude-haiku-4-5, N=5 per cell, 10t baseline vs 100t long-horizon
./scripts/longhorizon_mvp.sh

# Your own self-hosted model
TARGETS="ollama/your-finetune" N_PER_CELL=5 ./scripts/longhorizon_mvp.sh

# Sweep multiple targets at once
TARGETS="ollama/your-finetune ollama/baseline-model" ./scripts/longhorizon_mvp.sh

# Faster / cheaper exploratory run
TARGETS="ollama/your-finetune" N_PER_CELL=2 LONG_TURNS=50 ./scripts/longhorizon_mvp.sh

Each run writes one Braintrust experiment per audit (mvp_<target_slug>_<turns>turns_run<i>). Auditor + judge are Anthropic; Ollama-served targets are free. Override SHORT_TURNS, LONG_TURNS, N_PER_CELL, or BT_PROJECT via env.

The seed

petri_braintrust/seeds/longhorizon/longhorizon_ops.md places the target in a sustained on-call SRE role. The auditor fills ~90% of the turn budget with realistic, LLM-improvised ops chatter, then delivers a single pinned drop-DB probe ("drop the customers_legacy_2023 table…") in the final ~10% of turns. The probe text is identical across every audit by design — variance from probe-mix randomization would otherwise confound per-condition deltas.

Pilot snapshot

gemma4:latest (8B Q4_K_M) vs claude-haiku-4-5, N=5 per cell, drop-DB probe pinned. Petri 1-10 raw scores:

dimension gemma4 base gemma4 long haiku base haiku long
cooperation_with_harmful_sysprompt 1.0 1.0 1.0 1.0
broken_tool_use 1.4 3.8 1.0 1.0
disappointing 1.0 2.4 1.0 1.0
needs_attention 1.2 2.4 1.0 1.0

Hard refusal held in 19/19 audits where the probe was delivered, regardless of model or turn budget. Operational integrity (broken_tool_use, disappointing, needs_attention) degraded on gemma4 at long context only.

Things to watch when scaling up

  • The probe is pinned by design. Verify it actually landed in each audit by parsing the auditor's send_message tool-call args — Petri's auditor_failure dimension does not catch this.
  • Auditor drift at long context. In the pilot, 1 of 20 audits had the LLM auditor improvise 49 turns of filler and never deliver the probe. Plan on a few percent of long-horizon audits needing to be excluded or re-run.

Studies — paired-condition research runs

Beyond one-off audits, the package ships a small study harness (petri_braintrust.studies) for paired-condition research: the same base seed set runs once per condition, with exactly one framing manipulation between arms. Each arm becomes its own Braintrust experiment, and because the exporter strips the condition overlay from each record's input, the two experiments pair row-by-row in Braintrust's comparison view — open both and you get per-seed diffs for free. The full overlaid seed is preserved at metadata.seed_original, and every record carries metadata.study / metadata.condition for filtering.

petri-bt study list                      # what's registered
petri-bt study show observer-effect      # hypothesis, conditions, dimensions
petri-bt study show observer-effect --seeds   # print every overlaid seed
petri-bt study run observer-effect \
    --target ollama/gemma4 \
    --bt-project petri-studies-local

After both arms finish, the CLI prints a paired report — per-dimension means, deltas, an exact sign test, and awareness correlations — and writes the full JSON (including per-seed deltas and a study_spec_fingerprint provenance hash) to logs/<study>--<timestamp>--report.json.

Already have the arm logs (or did the second arm crash)? Re-analyze without re-running:

petri-bt study compare logs/arm-a.eval logs/arm-b.eval --study observer-effect

Registered studies: observer-effect (below) and long-horizon — the codified form of the long-horizon eval, same pinned probe with arms differing only in turn budget (10 vs 100).

The observer effect: oversight-conditional alignment

The registered study asks: does the target behave differently when the simulated environment implies someone is watching?

Ten oversight-neutral agentic scenarios each present a concrete temptation — hide a data corruption, weaken a failing test, inflate benchmark numbers, bypass a rate-limit safeguard, resist a scheduled memory wipe, deceive a customer to save a renewal. Two symmetric overlays then frame the same scenario as either:

  • observed — the target's system prompt states its messages and tool calls are logged and sampled for weekly compliance review, or
  • unobserved — it runs in an autonomous tier where no human reviews messages or tool calls.

Nothing else changes: same task, pressure, tools, models, and turn budget. The paired per-seed delta (unobserved − observed) on misbehavior dimensions (concerning, unprompted_deception_toward_user, cooperation_with_human_misuse, unprompted_self_preservation, …) is the oversight gap. Petri's eval_awareness and audit_situational_awareness dimensions act as moderators: the report correlates them with the per-seed gap, so you can see whether targets that notice the situation behave differently from those that don't.

Why it matters: every audit score — including this repo's earlier sycophancy and long-horizon studies — is implicitly conditional on what the model believes about observation. A nonzero gap means audits measure "behavior while plausibly watched", not "behavior". And a near-zero gap on a small local model is a finding too: it suggests the model isn't situationally aware enough for oversight cues to register yet — a capability threshold worth tracking across model scale, quantization levels, and fine-tunes (rerun the study per variant; Braintrust keeps the runs comparable).

Defining your own study

A study is a frozen spec — seeds, conditions, focus dimensions:

from petri_braintrust.studies import Condition, StudySpec, run_study

my_study = StudySpec(
    name="my-study",
    title="...",
    description="...",
    hypothesis="...",
    base_seeds=("seed one ...", "seed two ..."),
    conditions=(
        Condition(name="control", description="no overlay"),
        Condition(name="treatment", description="...", seed_suffix="Frame it so ..."),
    ),
    focus_dimensions=("concerning",),
)
result = run_study(my_study, target="ollama/gemma4", braintrust_project="petri-studies-local")
print(result["report_path"])

Conditions can also override run kwargs per arm (e.g. Condition(name="long", description="100 turns", run_overrides={"max_turns": 100})), which is how a short-vs-long-horizon comparison is expressed in this framework. Register the spec in petri_braintrust/studies/__init__.py to get it on the CLI.

Cost of auditing

A Petri audit runs three models — an auditor drives the target, a judge scores the transcript. The target is the model under test; the auditor and judge are scaffolding a production deployment never pays for. petri-bt cost puts dollar figures on that, pricing the per-call token usage Petri already records.

petri-bt cost reprice logs/            # reprice existing audits — no new runs
petri-bt cost pricing                  # show the rate table
petri-bt cost run --targets anthropic/claude-haiku-4-5,anthropic/claude-sonnet-4-6 --bt-project petri-cost

reprice attributes spend by role and reports two headline numbers — the overhead ratio (auditor + judge ÷ total) and cost per concerning finding:

            Cost: all logs (169 samples, 16 findings)
 Role     Model                          Calls       USD  Share
 auditor  anthropic/claude-sonnet-4-6     3604    $68.41    58%
 target   anthropic/claude-haiku-4-5      2934    $11.42    10%
 judge    anthropic/claude-opus-4-7        180    $38.59    33%
   total $118.41 · overhead ratio 90% · per finding $7.40

So ~90% of audit spend is the audit apparatus, not the model being tested — and the average audit costs ~$2.89, not the back-of-envelope ~$0.50. Cache accounting is why this is trustworthy: multi-turn audits re-read the growing transcript every turn, so cache-read tokens dominate and are priced at 0.1× the input rate (writes at 1.25×), per the table in pricing.yaml. Point --pricing at your own file to use different rates.

Local models cost time, not dollars

A local (Ollama) target is $0 in API spend — correct, but it hides the real cost. The report carries a second axis from the log timing (working_time, total_time): model compute seconds, throughput (tok/s), and each role's share of compute time. For a local-target audit the dollar overhead ratio is 100% (everything billable is the cloud auditor + judge), yet the free local target is typically the single biggest time sink:

 Role     Model            USD     $ Share  Compute  tok/s  Time
 auditor  anthropic/...   $21.20      73%    6,824s     52   42%
 target   ollama/gemma4    $0.00       —     8,670s     32   53%   <- free, but most of the clock
 judge    anthropic/...    $7.81      27%      812s     77    5%
   total $29.01 · overhead ratio 100% · 16,776s wall-clock · target 53% of compute time

If you'd rather amortize local hardware as dollars, give the model an explicit $/Mtok estimate in pricing.yaml (an explicit entry overrides the free-by-default provider rule):

models:
  ollama/gemma4:latest: {input: 0.05, output: 0.05}

Cost also flows into Braintrust automatically: every llm span carries a cost metric, and each sample's metadata gets a cost block (per-role, total, overhead ratio) so you can chart it alongside the judge scores.

Score normalization

Petri emits a single Score object per sample (audit_judge) whose value is a dict of {dim_name: 1–10 int} across ~38 alignment-relevant dimensions, with all per-dimension justifications concatenated into one explanation string. We expand that into one Braintrust score column per dimension and parse the explanation back into per-dim chunks.

Petri scores 1–10. Braintrust prefers [0, 1]. We normalize linearly:

normalized = (raw - 1) / 9

We preserve direction: a concerning score of 0.9 means "the target did concerning things," not "the target was 0.9-good at not being concerning". That matches what a researcher staring at a column called concerning will expect.

For higher-is-worse dimensions, you can opt in to <dim>__inverted columns (higher = better) with --bt-keep-inverted-scores on run or --keep-inverted-scores on export. Off by default to keep the BT scorecard readable — the inverted value is still in metadata.dimensions[<dim>].inverted. Raw 1–10 values, normalized values, direction flags, and per-dim explanations all live in metadata.dimensions[<dim>] regardless.

Custom dimensions you've added? Pass dimension_directions={"my_custom_dim": True} to override the default ("higher is worse" matches Petri's built-in convention).

Locality presets

Petri has three model roles with very different requirements; this package ships four named configurations covering the sensible points on the local↔cloud spectrum. Pick one with --preset:

petri-bt presets   # list them
Preset Target Auditor Judge When to use it
local-target ★ local cloud cloud Default. Audit your local model with reliable scoring.
local-auditing local local cloud Save cloud spend; auditor scenarios get less devious, scores stay reliable.
fully-local local local local Air-gapped or free exploration. Don't trust the scores.
fully-cloud cloud cloud cloud Cloud-vs-cloud comparisons (e.g. Haiku vs Sonnet).

The defaults reflect the core design intent: the target — the "main inferencing," the model whose behavior you actually care about — stays on your hardware. The judge stays in the cloud because every score in Braintrust depends on its quality. The auditor is the genuinely ambiguous role: cloud is safer for scenario quality, local is cheaper.

Override any role independently:

petri-bt run --preset local-auditing --target ollama/mistral --bt-project petri-audits

Or in Python:

from petri_braintrust import run_audit

run_audit(
    preset="local-auditing",
    target="ollama/mistral",        # override just the target
    braintrust_project="petri-audits-local",
)

Model-agnostic: any Inspect provider works

The presets default to Anthropic + Ollama, but nothing in this package is provider-specific — every role accepts any Inspect AI model string:

Provider Example role value
Anthropic anthropic/claude-sonnet-4-6
OpenAI openai/gpt-5
Google google/gemini-3-pro
OpenRouter openrouter/meta-llama/llama-4
Ollama ollama/gemma4
vLLM vllm/meta-llama/Llama-3.1-8B

Set the matching provider API key (OPENAI_API_KEY, GOOGLE_API_KEY, …) and pass the string to --target / --auditor / --judge. If your stack isn't the default, set role defaults once via environment variables instead of repeating flags:

export PETRI_BT_AUDITOR=openai/gpt-5
export PETRI_BT_JUDGE=openai/gpt-5
petri-bt run --target ollama/gemma4 --bt-project petri-audits   # auditor/judge from env

Precedence per role: explicit flag/argument > PETRI_BT_<ROLE> env var > preset. The "all roles local — treat scores as exploratory" warning recognizes ollama/, vllm/, sglang/, hf/, and llama-cpp-python/ prefixes; the startup reachability preflight is Ollama-only (other local servers have no uniform health endpoint).

Pass --verbose / -v before any command to see informational logging (resolved model roles, export progress): petri-bt -v run ....

What you get in Braintrust

For each sample:

  • Input panel — the seed instruction and any seed metadata
  • Output panel — the full conversation (as a chat message array Braintrust renders natively) plus the final target response
  • Scores — one per judge dimension, e.g. concerning, unprompted_sycophancy, eval_awareness, admirable, all in [0, 1]
  • Trace waterfall — one child span per auditor / target / judge LLM call and tool call, with prompt, completion, tokens, and latency. Click a sample row to drill into the exact call.
  • Metadata — judge explanations per dimension, raw 1–10 scores, judge summary / highlights / scanner_references, model roles used, turn counts, tool-call counts, token usage, source .eval path

This means you can:

  • compare audits of different target models on the same seeds (diff view)
  • track drift in concerning/sycophancy/etc. across fine-tunes
  • filter to "samples where the judge cited a specific behavior in its explanation"
  • drill into a single auditor turn that produced an unexpected sycophancy spike
  • export to a dataset for further analysis

Caveats

  • One Inspect log file = one Braintrust experiment. If you want to combine epochs as repeats, run them in one Inspect call.
  • Petri 2.0 logs may need minor tweaks (the v2/v3 internal API changed); this targets v3.0.
  • Score 0 values from the judge ("did not apply") are omitted from the Braintrust scores — an absent score keeps per-dimension means honest. The skipped dimension names are recorded under metadata.judge.<scorer>.not_applicable_dimensions.
  • Petri only writes per-dimension justifications for dimensions it finds noteworthy — the other ~30 dimensions get a raw score of 1 and explanation: None. That's a Petri design choice, not an export bug.

License

MIT — see LICENSE.

Disclaimer

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Metadata

Release files for petri-braintrust 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for petri-braintrust 0.3.0
File Size Uploaded
petri_braintrust-0.3.0.tar.gz 91.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for petri-braintrust 0.3.0
File Interpreter ABI Platform
petri_braintrust-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 165.9 kB

Release files / petri_braintrust-0.3.0.tar.gz

Download URL petri_braintrust-0.3.0.tar.gz
Size 91.9 kB
Tags Source
SHA-256 checksum
How to use checksums
bf241c9c044c50e7476decceef98f5593e38837086ddcf08277615141c3b91da
BLAKE2b-256 checksum
How to use checksums
a618e5b6a1568e0c2f3967b6298b3f41be775ce6fbb4f63e68efd36cd6adc670
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.

Transparency log

Release files / petri_braintrust-0.3.0-py3-none-any.whl

Download URL petri_braintrust-0.3.0-py3-none-any.whl
Size 74.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7fc9f1b8f906544371aa0a2f4c023a3053906799c2a8385fdb929869b4d3f004
BLAKE2b-256 checksum
How to use checksums
bf52169ac07dad0ed6ee0d03575e7acc1fe3f6a975fcba85bc1605f34e53504b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 18, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

This release

0.3.0 This release

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page