Skip to main content

hawk

Write per-sample kernels in Python, with derivatives. Part of the RAPTOR family.

hawk: one kernel, two machines, and its derivatives

Write a numerical kernel for one sample as a plain Python function. hawk compiles it for the GPU or the CPU and derives its gradient (reverse mode) and tangent (forward mode).

CI Docs License PyPI DOI

The RAPTOR family
hawk eagle
aether raptor

hawk is the kernel-authoring layer of the RAPTOR family: write a kernel once at the level of your application, and hawk derives its forward- and reverse-mode derivatives and compiles it for host or device through eagle. See where RAPTOR fits for the full four-part story.

Read the documentation — installation, a five-minute quickstart, tutorials, examples and the full Python API reference.

Write a kernel, get its gradient

Runs on CPU.

import pathlib, tempfile

import hawk
from hawk import Kernel, Mutable, Scalar, Vector
from hawk.diff import vjp
from hawk.math import dot

@hawk.kernel
def energy(v: Vector[3], out: Mutable[Scalar]):
    out = 0.5 * dot(v, v)

energy_vjp = Kernel("energy_vjp", vjp(energy, wrt=("v",)))
work = pathlib.Path(tempfile.mkdtemp())
bundle = hawk.build([energy, energy_vjp], work, targets=("host",))
import numpy as np

v = np.array([[1.0, 2.0, 3.0, 4.0], [0.0, 1.0, 0.0, 1.0], [0.0, 0.0, 1.0, 1.0]])
e = np.zeros(4)
hawk.run(hawk.load(work, "energy"), v=v, out=e)
print("energy:", e)
# energy: [0.5 2.5 5.  9. ]
bar_out = np.ones(4)             # seed: d(loss)/d(energy) = 1 for every sample
bar_v = np.zeros((3, 4))
hawk.run(hawk.load(work, "energy_vjp"), v=v, bar_out=bar_out, bar_v=bar_v)
print("gradient d(energy)/dv:")
print(bar_v)
# [[1. 2. 3. 4.]
#  [0. 1. 0. 1.]
#  [0. 0. 1. 1.]]

energy = 0.5 |v|^2, so d(energy)/dv = v exactly — the printed gradient above is the input v. Output above is the notebook's own: docs/content/tutorials/04_gradients_backward.ipynb. hawk.diff.jvp derives the forward-mode (tangent) twin the same way.

Five-minute quickstart · install: pip install raptor-hawk raptor-eagle matplotlib (CPU route, no extras), or pip install "raptor-hawk[cuda12]" "raptor-eagle[cuda12]" for the GPU route

Writing kernels

A kernel is a plain Python function decorated @hawk.kernel, one sample at a time; its parameters are its declared planes (Scalar, Vector[3], Mutable, ...) and its body writes ordinary arithmetic:

import hawk
from hawk import Mutable, Scalar, Terminated, Vector
from hawk.math import maximum, norm

@hawk.kernel
def running_apogee(position: Vector[3], terminated: Terminated,
                    r_max: Mutable[Scalar]):
    r_max = maximum(r_max, norm(position))
Running statistics: read it before you write it

A Mutable parameter such as r_max is an ordinary local variable: read it before you assign it and you get the value it held when THIS launch began, which is how a running statistic is written — a launch reads what an earlier launch left behind, and writes a new value on top of it. Your buffer remembers; the kernel reads what it remembered. The host owns that memory: it must initialise r_max before the first launch and preserve it between launches — hawk never zeroes or scratch-allocates a plane a kernel reads from. That memory is not differentiable: a launch-start read is a recurrence across launches, and hawk keeps no tape across them, so hawk.diff.vjp/jvp refuse a kernel that reads one — differentiate the per-launch term on its own instead. A STEP kernel's whole rollout is the exception a runtime handles: hawk.diff.tape(kernel, window) builds the step's taping twin, which records the state every step read, so a launching runtime can reverse the rollout window by window (Tapes and events).

Kernel kinds and returned outputs

A kernel may commit through several sinks — the places a kernel's result goes: declared Mutable parameters (Output.named(...)), a return <expr> committed into a synthesised slot (a result sink hawk creates for you rather than one you declared as a parameter; Output.returned(ttype, slot=...) names it), or both together — a returned acceleration alongside an ordinary diagnostic Mutable the body also writes:

from hawk import Param
from hawk.ext import Kind, Output

ACCEL = Kind("drag", output=Output.returned(Vector[3], slot="acc"))

@ACCEL
def drag(velocity: Vector[3], k: Param, speed: Mutable[Scalar]):
    speed = norm(velocity)          # an ordinary named sink
    return (-k * norm(velocity)) * velocity   # the returned slot, "acc"

Kind(...) also has a class-form spelling — sugar over the same object, one kernel-authoring style closer to a plugin author's own vocabulary: an annotated class attribute is a vocabulary entry, a plain-assigned one sets one of Kind's own fields (output, sink, guard, ...), and anything else refuses.

from hawk.ext import KernelKind, Output

class Accel(KernelKind, slug="drag"):
    output = Output.returned(Vector[3], slot="acc")

@Accel
def drag(velocity: Vector[3], k: Param):
    return (-k * norm(velocity)) * velocity

Threading

Free-threaded CPython (3.13t/3.14t) is supported: the compiled modules declare GIL-free operation and the GIL stays disabled after import. Any number of threads may call module-level functions, build, compile, plan and cache concurrently. Distinct objects may be used from distinct threads without synchronisation. One stateful object (a stream, capture, launcher, graph, composer, plan, pipeline, active set, host kernel or arg block) shared by several threads is memory-safe — its calls serialise and a consumed object raises — but the ORDER of those calls is the caller's responsibility, exactly as for a NumPy array or a CuPy stream. CUDA adds two rules of its own: a stream capture is begun, filled and ended by one thread, and while any capture is open no thread may synchronise the whole device (stream-level synchronisation is fine). GPU routes are supported on free-threaded 3.14; on 3.13t the CPU route runs. hawk's compile cache is shared safely between threads, and a sealed-path kernel's cache key follows the user headers it includes.

Install

pip install raptor-hawk raptor-eagle matplotlib          # CPU: no GPU, driver or CUDA packages (matplotlib is for the tutorials' plots)
pip install "raptor-hawk[cuda12]" "raptor-eagle[cuda12]"    # GPU: hawk compiles, eagle runs; [cuda13] on both for CUDA 13

Extras, platforms, requirements and the CPU-only route: installation.

Performance

Every number in this section is generated from the performance cards committed in eagle (benchmarks/perf_card and benchmarks/rk78_card): tools/sync_perf_claims.py rewrites them, and tests/test_perf_claims.py fails if this text, the snapshot docs/perf_claims.json or (with RAPTOR_EAGLE_ROOT set to an eagle checkout) the cards disagree. Kernels authored with hawk are what eagle's performance card times.

hawk + eagle (eagle.simulate) integrates 1,000,000 RK4 oscillators, each stopping at its own step, in 613 µs on an NVIDIA H100 80GB HBM3 (199 µs for 100,000), 2.5×–600× faster than NVIDIA Warp (2.5×), JAX (76×), CuPy (600×), PyTorch with torch.compile (130×) at N = 1,000,000 (1.1×–1700× at N = 100,000), in 40 MiB of GPU memory

— and, on the NVIDIA H100 80GB HBM3 reference GPU, the same hawk kernel, unmodified, integrates 1,000,000 adaptive RK7(8) orbits in 43.6 ms; on a CPU alone, through eagle's host team, the same batch takes 3.76 s on 8 threads of an AMD EPYC 9B45 (the no-GPU route, for machines without a GPU). This is the regime hawk + eagle's compaction targets (many samples stopping at different times); in other regimes the other tools hold their own. On a dense workload where nothing finishes early, NVIDIA Warp is the fastest arm on that H100 at N = 1,000,000 (1.71 ms vs 1.75 ms for eagle.simulate, which takes 2.5% longer), while at N = 10,000 on the same workload eagle.simulate is ahead (112 µs vs 121 µs). The development card the tutorials teach on is the Quadro P2000; its numbers are on the performance page next to every other device. See eagle's performance page for every number, every arm, including the ones where it doesn't win.

Wall time per tool for a million RK4 oscillators on the default GPU: eagle.simulate, NVIDIA Warp, JAX, CuPy and PyTorch; the numbers are on eagle's performance page.

The chart shows one GPU; the performance page has a tab for every device and CPU measured.

The same hawk kernel also runs on a CPU alone, through eagle's host team: on an AMD EPYC 9B45 (8 cores, 16 logical CPUs) the 8-thread spread S=1000 batch of 1,000,000 samples takes 142 ms. eagle's performance page has a tab for every CPU and GPU measured, with Numba, JAX, PyTorch, NumPy and multiprocessing on the CPU cards, each with the setting where it fits best; on some cells and CPUs another tool is ahead, and the card shows which.

Going deeper

The pip-only device compile, directly

The device compile hawk.artifact.build/build_bundle use when no nvcc is on $PATH goes through hawk.compile.device/hawk.compile.cubin; the same entry points are usable directly, for an ad hoc CUDA C++ source string that was never authored as a traced hawk kernel at all:

from hawk.compile import cubin, cubin_available

if cubin_available():
    image = cubin(source)          # DeviceImage(image=<SASS bytes>, target="cubin", arch="sm_XX")

cubin_available() never raises; device(source, target="ptx") is the alternative when PTX (the portable intermediate form NVRTC can also emit) is what a caller needs, guarded against a driver too old to JIT a newer NVRTC's PTX (target="cubin" needs no such guard — it is already SASS, the GPU's own machine code). Headers come from aether_dsc's sealed payload — a copy of the headers hawk's device compiler reads from directly, bundled into the wheel — never from disk.

Build and test from a source checkout (development)

Clone aether and eagle next to this checkout (so ../aether and ../eagle sit beside hawk/), then install aether's sealed header payload before hawk itself:

pip install ../aether/dsc
pip install -e .[test]
pytest -m "not gpu"

The compiled half (hawk._core) is a nanobind extension built through scikit-build-core; pip install -e . builds it via CMakeLists.txt, resolving the aether/eagle C++ header roots from those sibling checkouts (or $HAWK_AETHER_INCLUDE/$HAWK_EAGLE_INCLUDE). -m "not gpu" deselects the tests that need a CUDA GPU and cupy; most of the rest additionally need eagle installed as a Python package to execute traced kernels on host or device (see the "Python package" section of eagle's README).


hawk write it (this repo) · eagle run it · aether the numerics core · raptor the shared contracts — the RAPTOR family

Apache-2.0 (see LICENSE and NOTICE) · cite via "Cite this repository" (CITATION.cff; every tagged release is archived on Zenodo: doi:10.5281/zenodo.23250242) · built to make GPU computing accessible on modest hardware, for research and education. Collaboration is the point, and a citation is the currency — get in touch.

Metadata

Release files for raptor-hawk 0.6.3

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

Source distribution (sdist)

Source distribution for raptor-hawk 0.6.3
File Size Uploaded Provenance
raptor_hawk-0.6.3.tar.gz 1.8 MB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for raptor-hawk 0.6.3
File
raptor_hawk-0.6.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 free-threading Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.26+ x86-64, Linux glibc 2.28+ x86-64 Details
raptor_hawk-0.6.3-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.28+ x86-64, Linux glibc 2.26+ x86-64 Details

Total release size: 6.3 MB

Release files / raptor_hawk-0.6.3.tar.gz

Download URL raptor_hawk-0.6.3.tar.gz
Size 1.8 MB
Tags Source
SHA-256 checksum
How to use checksums
97e72d85c168c8a9af7bb9fa1f5448ca16d6fbbb09fee6b17986d93140a04168
BLAKE2b-256 checksum
How to use checksums
cdaa6a93e35350c9568aef1d8ac9a92432d4c38f37cc74c68bd99c822b12045b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 574.0 kB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
55fb00afac4d93763bad0f5f714a0ba24fe1c2810160aebf9526948a086fb34e
BLAKE2b-256 checksum
How to use checksums
99626902c26ac5f433b1cf43944bc7dafed79a7fefaed29a5be03849b4c83fb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 571.2 kB
Tags CPython 3.14 Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
0fd2cf0588a20490eb6ca56058f86b832d7e5058f05e5ea8bd75d65ab7619d9a
BLAKE2b-256 checksum
How to use checksums
a5597d82b72825aa5274effef5b50292af322359925b02169c005db3406debc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 573.9 kB
Tags CPython 3.13 CPython 3.13 free-threading Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
096377f5c1aa1254283b2646b04cd32b0252d6eb0e6d93af5b5c0a041a190d3f
BLAKE2b-256 checksum
How to use checksums
82116ecd4ee7796a351788bdd3e9b802251281552456080ba644769ca60e3b3d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 571.0 kB
Tags CPython 3.13 Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d03f6295870b8d0aff460f5ce8efb9bae8279e9a2c656e374ac8f3b75f2220df
BLAKE2b-256 checksum
How to use checksums
3a9122ea4dffe9601074adb0b7c2f5599f6f9881479424f9e4f244c669baa9db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 571.0 kB
Tags CPython 3.12 Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
01e54614653fcff171e0ff372139660bb9ffe872b44faf846008dc2d2f2d6d54
BLAKE2b-256 checksum
How to use checksums
94a50f9f59e9b91824b4d4af7ed153725b66a613647ab6ccefa29686aa3f644f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 571.4 kB
Tags CPython 3.11 Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
08fc3e16d7212821c82ff59bc25db0582a9fbfcf8bdf0972e8ea9a7deb0aeac8
BLAKE2b-256 checksum
How to use checksums
800aac8bc36bd7db354077ccfc9b7263017ad9d1ac5c2eaeb2f5322786940684
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 571.8 kB
Tags CPython 3.10 Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
1823cbe15698124ab55ea12d145faccbca68939dabdc2cc201a0d791d4264808
BLAKE2b-256 checksum
How to use checksums
115428d74a5b4d882d998668a7d41b7789b6771c6bf03cbb564661653f80503f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Release files / raptor_hawk-0.6.3-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

Download URL raptor_hawk-0.6.3-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
Size 565.3 kB
Tags CPython 3.9 Linux glibc 2.26+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
7a9b8aff576ba10b2d3b9c4737a09bd0ecf8085124906159bfd64b00a76796c3
BLAKE2b-256 checksum
How to use checksums
8c2187f6c33232410dd4e9ab253033fd414e96c4870456e82105457ccf3d28bc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 20, 2026.

Transparency log

Security for raptor-hawk 0.6.3

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.

Full provenance

All 9 files in this release have been uploaded with provenance metadata.

Select from 9 files

Attestation for raptor_hawk-0.6.3.tar.gz

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 Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

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