Skip to main content

Open-source iterative threat modeling powered by LLMs - STRIDE + MAESTRO frameworks with DREAD scoring

Project description

Paranoid

Open-source, self-hosted, iterative threat modeling powered by LLMs.

Paranoid takes system descriptions (text, diagrams, or code via MCP) and produces comprehensive STRIDE + MAESTRO threat models through an LLM-powered pipeline with deterministic fallback. Configure 1–15 automated iteration passes, then review threats in a human-in-the-loop approve/reject cycle.

Features

  • Zero Infrastructure: SQLite + sqlite-vec. One command to run: docker compose up [Coming Soon]
  • Multi-Provider LLM: Anthropic, OpenAI, or Ollama (fully local/air-gapped)
  • Dual Framework Support: STRIDE (traditional) + MAESTRO (AI/ML) auto-detected or run in parallel
  • DREAD Risk Scoring: Automatic risk assessment with 5 dimensions (0-10 scale each, averaged) for severity classification
  • Structured Input Templates: Tagged templates for component descriptions with assumption enforcement in the prompts
  • Iterative Refinement: 1–15 configurable iteration passes with gap analysis
  • Code-as-Input: Semantic code extraction via context-link MCP — --code /path/to/repo grounds threats in actual implementation
  • Image-as-Input: Architecture diagram support via --diagram arch.png (vision API) or --diagram flow.mmd (Mermaid text)
  • Deterministic Rule Engine: 109 curated STRIDE/MAESTRO/OWASP patterns run alongside the LLM and are merged into the final output
  • Persistent Results: Every run is saved to SQLite automatically — inspect past models with paranoid models list / paranoid models show
  • Export Formats: JSON (simple/full), SARIF (GitHub Security integration), Markdown (PRs / Confluence / Notion), PDF (security review sign-off)
  • Post-Run Export: Re-export any saved model in any format with paranoid models export — run once, export many times
  • Model Management: paranoid models delete removes a saved model and all its data; paranoid models prune bulk-deletes by age or status
  • CI/CD Ready: CLI + GitHub Action with SARIF upload for automated threat detection

Quick Start

Step 1: Install

Choose the method that works best for you:

PyPI (Recommended):

pip install paranoid-cli
paranoid --version

Docker [Coming Soon]:

docker pull theastiv/paranoid:latest

docker run --rm \
  -v $(pwd):/workspace \
  -e ANTHROPIC_API_KEY=sk-ant-xxx \
  theastiv/paranoid:latest \
  paranoid run /workspace/system.md

Standalone Binary (No Python Required):

Download the pre-built binary for your platform from GitHub Releases:

Platform Binary
Linux x86_64 paranoid-linux-x64
macOS ARM64 (Apple Silicon) paranoid-macos-arm64
Windows x64 paranoid-windows-x64.exe
# Linux/macOS
chmod +x paranoid-linux-x64
./paranoid-linux-x64 --help

From Source (Development):

git clone https://github.com/theAstiv/paranoid
cd paranoid
pip install -e .

Step 2: Configure

Option A: Interactive Wizard (Recommended)

paranoid config init

# Follow prompts to configure:
#   - LLM Provider (Anthropic/OpenAI/Ollama)
#   - API Key
#   - Model name
#   - Default iterations

paranoid config show

Option B: Environment Variables

cp .env.example .env

Edit .env and add your provider configuration:

# Anthropic (Recommended)
ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxxx
DEFAULT_PROVIDER=anthropic
DEFAULT_MODEL=claude-sonnet-4-20250514

# OR OpenAI
OPENAI_API_KEY=sk-xxxxxxxxx
DEFAULT_PROVIDER=openai
DEFAULT_MODEL=gpt-4o

# OR Ollama (fully local, no API key)
OLLAMA_BASE_URL=http://localhost:11434
DEFAULT_PROVIDER=ollama
DEFAULT_MODEL=llama3

# Optional: path to context-link binary for --code flag
# If unset, Paranoid looks for bin/context-link then PATH
CONTEXT_LINK_BINARY=/usr/local/bin/context-link

# Optional: restrict CORS origins (default: * allows all)
# Comma-separated for multiple origins
CORS_ORIGINS=https://app.example.com,https://staging.example.com

Step 3: Run Your First Threat Model

# Run with an example
paranoid run examples/stride-example-api-gateway.md

# With architecture diagram (Mermaid, PNG, or JPG)
paranoid run examples/stride-example-api-gateway.md \
  --diagram examples/stride-api-gateway-architecture.mmd

# With your own system description
paranoid run my-system.md

# See all options
paranoid run --help

Expected Output:

Configuration:
  Provider: anthropic
  Model: claude-sonnet-4-20250514
  Iterations: 3
  Framework: STRIDE

[>] summarize: Generating system summary...
[OK] summarize: Summary generated: 196 chars
[>] extract_assets: Identifying assets and entities...
[OK] extract_assets: Identified 14 assets/entities
[>] extract_flows: Extracting data flows and trust boundaries...
[OK] extract_flows: Identified 12 flows, 6 boundaries
[>] generate_threats [iter 1]: Generating threats (iteration 1/3)...
[OK] generate_threats [iter 1]: Generated 10 threats
...
[OK] complete: Pipeline complete: 2 iterations, 17 threats

================================================================================
THREAT MODEL COMPLETE
================================================================================
Total Threats:      17
Iterations:         2
Duration:           115.0 seconds
Output:             stride-example-api-gateway_threats.json

Expected Runtime:

  • Claude Sonnet: ~30-60 seconds (3 iterations)
  • GPT-4: ~45-90 seconds (3 iterations)
  • Ollama (local): 2-5 minutes (depends on hardware)

CLI Reference

Running Threat Models

# Basic usage (auto-detects framework from input)
paranoid run system.md

# Structured templates (auto-detects STRIDE vs MAESTRO)
paranoid run examples/stride-example-api-gateway.md
paranoid run examples/maestro-example-rag-chatbot.md

# JSON output (simple format - lightweight, ~2-3 KB)
paranoid run system.md --output threats.json

# JSON output (full format - complete models + DREAD + events, ~45 KB)
paranoid run system.md --format full -o complete.json

# SARIF export for GitHub Security integration
paranoid run system.md --format sarif -o threats.sarif

# Markdown export for PRs, Confluence, and Notion
paranoid run system.md --format markdown -o threats.md

# Markdown export with auto-suffix (no extension needed)
paranoid run system.md --format markdown -o threats

# PDF export for security review sign-off and archival
paranoid run system.md --format pdf -o report.pdf

# PDF export with auto-suffix
paranoid run system.md --format pdf -o report

# Force dual framework (STRIDE + MAESTRO in parallel)
paranoid run system.md --maestro

# Override iteration count (1-15)
paranoid run system.md --iterations 7

# Override framework auto-detection
paranoid run system.md --framework MAESTRO

# Override provider and model for a single run (without changing config)
paranoid run system.md --provider openai --model gpt-4o
paranoid run system.md --provider anthropic --model claude-opus-4-5

# Quiet mode (suppress real-time output, show only summary)
paranoid run system.md --quiet

# Verbose mode (show detailed event data with complete models)
paranoid run system.md --verbose

# Code-as-input: ground threats in actual source code (requires context-link binary)
paranoid run system.md --code /path/to/repo

# Image-as-input: include architecture diagram (PNG/JPG via vision API)
paranoid run system.md --diagram architecture.png

# Image-as-input: Mermaid diagram as text (all providers)
paranoid run system.md --diagram flow.mmd

# Combined: description + diagram + code context
paranoid run system.md --diagram arch.png --code /path/to/repo

Inspecting Saved Models

Every paranoid run saves its results to SQLite automatically. Use the models subcommand to browse and inspect past runs without re-running the pipeline.

# List recent threat models (most recent first)
paranoid models list

# Limit results
paranoid models list --limit 50

# Machine-readable JSON output
paranoid models list --json

# Show threats for a saved model — partial ID works (first 8 chars)
paranoid models show a1b2c3d4

# Full UUID also accepted
paranoid models show a1b2c3d4-e5f6-7890-abcd-ef1234567890

# Show threats without mitigations
paranoid models show a1b2c3d4 --no-mitigations

# JSON output (model metadata + threats array)
paranoid models show a1b2c3d4 --json

# Export a saved model to Markdown (run once, export many times)
paranoid models export a1b2c3d4 --format markdown -o report.md

# Export to PDF for security review sign-off
paranoid models export a1b2c3d4 --format pdf -o report.pdf

# Export to SARIF for GitHub Security
paranoid models export a1b2c3d4 --format sarif -o findings.sarif

# Export to JSON (simple summary or full raw dump)
paranoid models export a1b2c3d4 --format simple -o threats.json
paranoid models export a1b2c3d4 --format full -o complete.json

# Default output path (no -o flag): {id_prefix}_{format}.{ext} in cwd
paranoid models export a1b2c3d4 --format markdown

# Delete a saved model and all its data (prompts for confirmation)
paranoid models delete a1b2c3d4

# Delete without prompt (for scripting/CI)
paranoid models delete a1b2c3d4 --yes

# Prune old models (older than 30 days)
paranoid models prune --older-than 30

# Prune all failed models without prompting
paranoid models prune --status failed --yes

# Combine filters: old AND failed
paranoid models prune --older-than 7 --status failed

Example models list output:

  ID          Title                 Framework  Threats  Status      Date
  --------------------------------------------------------------------------
  a1b2c3d4    api-gateway           STRIDE           23  completed   2026-04-01 14:32
  e5f6g7h8    auth-service          STRIDE           17  completed   2026-03-28 09:15
  c9d0e1f2    rag-chatbot           MAESTRO          31  completed   2026-03-25 11:04

Example models show output:

  Threat Model: api-gateway
  ============================================================
  ID:           a1b2c3d4-...
  Framework:    STRIDE
  Threats:      23
  Iterations:   3

  THREATS
  ------------------------------------------------------------
  [1] SQL Injection  (Tampering)  pending
      Target: PostgreSQL DB  |  Impact: High  |  Likelihood: Medium
      → Use parameterized queries
      → Apply input validation
  ...

Configuration Management

# Interactive setup wizard
paranoid config init

# Reconfigure (overwrite existing config)
paranoid config init --force

# Display current configuration
paranoid config show

# Config file location: ~/.paranoid/config.json

Version Info

# Show version, Python version, dependencies, and current configuration
paranoid version

Output Formats

JSON Simple (default, ~2-3 KB)

Lightweight threat summaries for CI/CD dashboards and quick reviews.

{
  "execution": {
    "total_threats": 17,
    "iterations_completed": 2,
    "duration_seconds": 115.0
  },
  "threats": [
    {
      "name": "JWT Token Forgery",
      "category": "Spoofing",
      "target": "API Gateway",
      "impact": "Complete authentication bypass",
      "likelihood": "Medium",
      "mitigation_count": 3
    }
  ]
}

JSON Full (~45 KB)

Complete Pydantic models with DREAD scores and full pipeline event audit trail. Suitable for detailed analysis, archival, and integration with other tools.

paranoid run system.md --format full -o complete.json

Markdown (~4–15 KB)

Human-readable reports for PRs, Confluence, Notion, and security review documents. Contains a summary table, per-category threat sections, DREAD scores, and tagged mitigations.

paranoid run system.md --format markdown -o threats.md

Output structure:

# Threat Model: my-system

**Framework:** STRIDE | **Model ID:** `a1b2c3d4` | **Generated:** 2026-04-02

## Summary
| # | Threat | Category | Target | Likelihood | DREAD |
...

## Threats

### Tampering

#### 1. SQL Injection
**Target:** Database | **Likelihood:** High | **Impact:** Data breach
**DREAD:** 7.5/10 *(D:8 R:7 E:8 A:6 Di:7)*

> An attacker exploits unparameterized queries...

**Mitigations:**
- [P] Use parameterized queries / prepared statements
- [D] Enable query anomaly logging

Pass include_header=False when calling export_markdown() directly to omit the H1 heading and metadata block for embedding into existing documents.

PDF (~50–200 KB)

Structured PDF reports for security review sign-off, archival, and sharing with stakeholders who don't use Markdown. Contains the same content as the Markdown export: title, metadata, summary table, per-category threat sections, DREAD scores, and tagged mitigations. Produced via reportlab — no external binaries required.

paranoid run system.md --format pdf -o report.pdf
paranoid models export a1b2c3d4 --format pdf -o report.pdf

SARIF (GitHub Security Integration)

SARIF 2.1.0 format for GitHub Security tab, GitLab, VS Code, and Azure DevOps:

paranoid run system.md --format sarif -o threats.sarif

GitHub Actions Integration:

name: Threat Model

on: [push, pull_request]

jobs:
  threat-model:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run threat modeling
        run: |
          pip install paranoid-cli
          paranoid run system.md --format sarif -o threats.sarif
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

      - name: Upload to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: threats.sarif

Code-as-Input (--code)

Ground threats in actual source code using the context-link MCP binary. When --code is provided, Paranoid extracts a semantically relevant slice of the codebase and threads it through every pipeline node.

paranoid run system.md --code /path/to/repo
paranoid run system.md --code /path/to/repo --iterations 5
paranoid run system.md --diagram arch.png --code /path/to/repo  # combined

How it works:

  1. Three-tier extraction funnel (50KB budget, ~12.5K tokens):

    • Semantic search: semantic_search_symbols finds symbols relevant to the threat model description
    • Code body extraction: get_code_by_symbol fetches full source for top results
    • File skeletons: get_file_skeleton fills remaining budget with structural outlines
  2. Code summary step: _deterministic_code_summary() extracts a focused ~2KB CodeSummary (tech stack, entry points, auth patterns, data stores, security observations) from CodeContext using file-extension mapping, import scanning, and keyword matching — no LLM call required. summarize_code() (LLM-backed) is available as an opt-in upgrade path when pattern matching isn't sufficient.

  3. Full pipeline threading: The CodeSummary is passed to all downstream nodes — extract_assets, extract_flows, generate_threats, and gap_analysis — so threats reference actual implementation details.

  4. Deterministic extraction: _deterministic_code_summary() covers tech stack from file extensions, HTTP routes from decorator patterns, auth/DB/HTTP-client keywords, and security anti-patterns (eval(), pickle.load, shell=True, SQL string concatenation). The pipeline never silently drops code context.

Installing context-link:

context-link is a standalone Go binary that indexes your repository and serves an MCP tool interface over stdio. Get it from github.com/context-link-mcp/context-link:

# Option 1: pre-built binary (recommended — no Go toolchain required)
# Download the binary for your platform from the GitHub Releases page:
# https://github.com/context-link-mcp/context-link/releases/latest
# Then place it at bin/context-link or add it to PATH.

# Option 2: build from source (requires Go 1.22+)
git clone https://github.com/context-link-mcp/context-link
cd context-link
CGO_ENABLED=1 go build -o context-link ./cmd/context-link
# Move the resulting binary to bin/context-link or PATH

Requirements:

  • context-link binary at bin/context-link (relative to working directory), on PATH, or at the path set by CONTEXT_LINK_BINARY
  • Binary discovery order: explicit CONTEXT_LINK_BINARY env var → ./bin/context-linkshutil.which("context-link")
  • If the binary is not found, Paranoid logs a warning and continues without code context

Error handling: Every MCP failure degrades gracefully — binary not found, subprocess crash, tool call error, and index timeout all produce a warning and allow the pipeline to continue with text-only input.


Image-as-Input (--diagram)

Supply an architecture diagram alongside your text description. Paranoid passes it to every pipeline node for richer threat coverage.

# PNG or JPG via vision API
paranoid run system.md --diagram architecture.png
paranoid run system.md --diagram architecture.jpg

# Mermaid (.mmd) as text — works with all providers
paranoid run system.md --diagram flow.mmd

# Combined with code context
paranoid run system.md --diagram arch.png --code /path/to/repo

Supported formats:

Format Mechanism Size Limit
PNG Vision content block (base64) 5MB
JPG/JPEG Vision content block (base64) 5MB
Mermaid .mmd <architecture_diagram> XML tag (text) 100KB

Provider support:

Provider PNG/JPG Mermaid
Anthropic (all models) Full support Full support
OpenAI gpt-4o, gpt-4o-mini Full support Full support
OpenAI other models Not supported (use gpt-4o) Full support
Ollama Logs warning, continues without image Full support

How it works:

  • PNG/JPG: The image is base64-encoded and passed as a vision content block in the provider's native format (Anthropic image content block; OpenAI image_url data URI). Each prompt's <architecture_diagram> instruction is replaced with a vision-specific directive.
  • Mermaid: The .mmd file is read as UTF-8 text and injected as <architecture_diagram> XML in the prompt. All providers parse Mermaid syntax natively — no rendering required.
  • Pipeline threading: DiagramData threads through all 5 pipeline nodes: summarize, extract_assets, extract_flows, generate_threats, and gap_analysis.

Structured Input Templates

Paranoid supports rich XML-tagged templates for better context and assumption enforcement. See Input-template.md for the full template reference and examples/ for working examples.

STRIDE Template (traditional systems): Component description with technology stack, interfaces, data handling, and 6 structured assumption sections.

MAESTRO Template (AI/ML systems): Extended component description with mission alignment, agent profile, and 9 structured assumption sections.

Model Configuration

Use Claude Sonnet (or newer) for reliable structured output generation.

Model Status Notes
claude-sonnet-4-20250514 Recommended Validated end-to-end, reliable for production
claude-haiku-4-5-20251001 Not recommended Fails with JSON parsing errors on complex outputs
gpt-4o Supported Works well, also supports vision (--diagram)
Ollama (Llama 3 70B+) Supported Fully local, no external API calls

Architecture

  • Backend: FastAPI + SQLite + sqlite-vec (loaded via sqlite_vec.loadable_path() — works on Windows without manual DLL installation)
  • Frontend: Planned (v1.0 is CLI-only)
  • LLM Providers: Anthropic / OpenAI / Ollama (protocol-based, swappable)
  • Pipeline: Plain async functions (no LangChain, no LangGraph)
  • Embeddings: Local via fastembed (ONNX, BAAI/bge-small-en-v1.5)
  • Models: Pydantic v2 for all data validation
  • Frameworks: STRIDE (traditional) + MAESTRO (AI/ML security)
  • Code context: context-link MCP binary (Go) + MCPCodeExtractor async context manager
  • Image input: backend/image/ package — encoder.py (PNG/JPG base64), mermaid.py (text load), validation.py (size/format)

Python API:

from backend.pipeline.runner import run_pipeline_for_model
from backend.providers.anthropic import AnthropicProvider
from backend.models.enums import Framework

provider = AnthropicProvider(model="claude-sonnet-4-20250514", api_key="your-key")

async for event in run_pipeline_for_model(
    model_id="web-app-001",
    description="E-commerce web application...",
    framework=Framework.STRIDE,
    provider=provider,
    max_iterations=3,
):
    print(f"[{event.step}] {event.message}")

Testing

# Run unit/integration tests (no API key required)
pytest tests/ -v

# Run end-to-end pipeline test (requires ANTHROPIC_API_KEY)
pytest tests/test_pipeline_e2e.py -v

# Validate structured input parser (no API key required)
python examples/test_structured_input.py

# Lint
ruff check backend/ cli/
ruff format backend/ cli/

Troubleshooting

Authentication errors:

  • Check your API key is correct in .env or ~/.paranoid/config.json
  • For Anthropic, ensure billing is set up and key starts with sk-ant-api03-

Module not found:

pip install -e .  # or: pip install paranoid-cli

Ollama connection refused:

ollama serve  # start Ollama first, then run paranoid

--code flag: context-link binary not found:

Install context-link from github.com/context-link-mcp/context-link (pre-built binaries on the Releases page), then make it available to Paranoid:

# Option 1: set env var pointing to the binary
export CONTEXT_LINK_BINARY=/path/to/context-link

# Option 2: place binary at bin/context-link relative to working directory

# Option 3: add context-link to PATH

If the binary is missing, Paranoid logs a warning and continues without code context.

sqlite-vec not loading (Windows "module not found"):

This was a known issue on Windows where a bare vec0 extension name was used. It is fixed in the current release — the extension is now loaded via the absolute path from the bundled sqlite-vec Python package (sqlite_vec.loadable_path()), which resolves correctly on all platforms. No manual DLL installation required; pip install paranoid-cli includes everything.

--diagram with OpenAI and vision errors: Only gpt-4o and gpt-4o-mini support JSON structured output together with vision. Other OpenAI models that support vision do not support JSON mode simultaneously. Switch to gpt-4o or use Anthropic.

--diagram with Ollama: Ollama does not support vision for most models. Paranoid logs a warning and continues without the image. Use --diagram flow.mmd (Mermaid text) instead — all providers support Mermaid.

macOS binary "developer cannot be verified":

xattr -d com.apple.quarantine paranoid-macos-arm64

Windows "Windows protected your PC": Click "More info" then "Run anyway", or add an exception in Windows Defender.

Platform Support

Platform PyPI Docker Binary
Ubuntu 20.04+ Yes Yes Yes
Debian 11+ Yes Yes Yes
RHEL 8+ Yes Yes Yes
macOS 11+ (Intel) Yes Yes No
macOS 11+ (ARM64) Yes Yes Yes
Windows 10+ Yes Yes Yes
WSL2 Yes Yes Yes

Documentation

Developer docs:

Development Status

v1.3.0 — CLI production-ready, available on PyPI and as standalone binaries.

Completed: Core pipeline (8 nodes, iteration logic, SSE, dual framework), LLM providers (Anthropic/OpenAI/Ollama), STRIDE + MAESTRO prompts, structured input templates, JSON + SARIF + Markdown + PDF export, DREAD scoring, CLI with config wizard, code-as-input via context-link MCP (--code), image-as-input via vision API and Mermaid text (--diagram), deterministic rule engine (109 curated patterns, RAG retrieval), full SQLite persistence (every run saved with assets/flows/threats/DREAD), paranoid models list/show/export/delete/prune commands, --provider/--model run-time overrides, packaging and release automation.

Future (v2.0+): REST API routes, frontend (Svelte UI), multi-user collaboration, provider offline fallback (rule-engine-only mode).

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

paranoid_cli-1.4.0.tar.gz (234.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

paranoid_cli-1.4.0-py3-none-any.whl (244.9 kB view details)

Uploaded Python 3

File details

Details for the file paranoid_cli-1.4.0.tar.gz.

File metadata

  • Download URL: paranoid_cli-1.4.0.tar.gz
  • Upload date:
  • Size: 234.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for paranoid_cli-1.4.0.tar.gz
Algorithm Hash digest
SHA256 9ad78c5507a029049c54b66acab291f64dab27614501a1484bbc42e1aa8bd31b
MD5 fdafa124c286b1a55579f80d18b7b37b
BLAKE2b-256 3fdbd853d6fe335d191caf8bd8da978f1d7bd386defeb509bc418f383079877c

See more details on using hashes here.

Provenance

The following attestation bundles were made for paranoid_cli-1.4.0.tar.gz:

Publisher: release.yml on theAstiv/paranoid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file paranoid_cli-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: paranoid_cli-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 244.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for paranoid_cli-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4614f1a5e09d6bdacf8597d39cd362bd9cf08a5113167920ed32b69041b67176
MD5 78f3601ee9683fdac52ec1ab4ed012fc
BLAKE2b-256 7b491edf0609f6a088d7f346b84bdd812a80021b463d5daaddbf218d6083ee29

See more details on using hashes here.

Provenance

The following attestation bundles were made for paranoid_cli-1.4.0-py3-none-any.whl:

Publisher: release.yml on theAstiv/paranoid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page