Skip to main content

🧰 disco-toolbox

A toolbox for disco simulation models.

PyPI License: Apache-2.0 Build Tests

disco-toolbox contains reusable utilities intended to be embedded in disco models and supporting code. The toolbox is deliberately small and focused: each subpackage should solve one clear problem well, with an emphasis on correctness, testability, and performance.


🧭 Overview

  • Python ≥ 3.11
  • Key dependencies: python-graphblas, numpy, scipy (orderbook uses dense numpy arrays; GraphBLAS is used elsewhere in the toolbox)
  • Includes optional C++/pybind11 and Cython extensions for hot paths (built with scikit-build-core).

📦 Installation

pip install disco-toolbox

📚 Subpackages

toolbox.orderbook

A compact order book for simulation loops (fast C++/pybind11 core):

  • Store outstanding orders as dense numpy.ndarray (float64) vectors
  • Keys are stored as opaque bytes (so you can pack identifiers however you like)
  • Allocate available capacity/stock against orders with a greedy strategy
  • Remove fully fulfilled orders during allocation
  • Supports pickling / unpickling for checkpointing

Quick example

import numpy as np
from toolbox.orderbook import Orderbook

ob = Orderbook()
ob.append(b"abc", np.array([1, 2, 3], dtype=np.double))
ob.append(b"def", np.array([4, 5, 6], dtype=np.double))

stock = np.array([5, 5, 5], dtype=np.double)
allocations = ob.allocate_greedy(stock)

for key, alloc in allocations:
    print(key, alloc)

print("remaining:", stock)

toolbox.calendar

Calendar-aware time arithmetic for simulation models (Cython-accelerated hot path):

  • Define working-time patterns via a cyclic weight array — full days, non-working days, or partial days
  • Add non-repeating holiday overrides by absolute day index
  • Compute elapse(start, duration) -> finish: the calendar time at which duration working units have elapsed since start
  • Accepts and returns both scalars and NumPy arrays (any broadcastable shape)
  • Compiled to a dense prefix-sum array at construction time; elapse is a single binary search — O(log H) per element

Quick example

import numpy as np
from toolbox.calendar import Calendar

# Mon–Fri = 1 working day, Sat–Sun = 0
cal = Calendar([1, 1, 1, 1, 1, 0, 0])

# Add public holidays
cal.add_holiday(0)        # Monday 0 is a bank holiday
cal.add_holiday(1, 0.5)   # Tuesday 1 is a half-day

# Scalar
finish = cal.elapse(start=0.0, duration=5.0)
print(finish)   # 9.0  (loses Mon, half Tue)

# NumPy arrays
starts    = np.array([0.0, 7.0, 14.0])
durations = np.array([5.0, 3.0,  1.0])
print(cal.elapse(starts, durations))

toolbox.capacity

Fixed-capacity token pool for scheduling jobs across parallel resources:

  • Models a multi-server queue where each token represents a parallel resource (server, machine, worker)
  • Jobs are assigned greedily to the earliest-free token — no sequencing decisions are made
  • Accepts a single duration (scalar) or an ordered vector of durations; vector jobs are assigned in occurrence order
  • Optional calc_finish integration: finish times are computed rather than wall-clock time

Quick example

import numpy as np
from toolbox.capacity import Capacity
from toolbox.calendar import Calendar

# Two parallel resources on a Mon–Fri calendar
cal = Calendar([1, 1, 1, 1, 1, 0, 0])
cap = Capacity(2, calc_finish=cal.elapse)

# Single job
start, finish = cap.process(epoch=0.0, duration=3.0)
print(start, finish)   # 0.0  3.0

# Batch of jobs assigned in order
starts, finishes = cap.process(epoch=0.0, duration=np.array([5.0, 5.0, 2.0, 2.0]))
print(starts)    # [0. 0. 5. 5.]   both tokens occupied for first two jobs
print(finishes)  # [5. 5. 8. 8.]   next two wait for weekend, finish Monday

toolbox.distributions

Small, simulation-oriented distribution utilities on top of SciPy:

  • Generic, registry-backed moment fitting via fit_moments.fit(...) returning standard SciPy frozen distributions
  • Custom distributions:
    • rectnorm: rectified normal distribution (X = max(0, Z) where Z ~ Normal(mu, sigma))
    • conditional: zero-inflated wrapper around a base SciPy distribution

Quick example

import numpy as np
from numpy.random import default_rng
from scipy import stats
from toolbox.distributions import fit_moments
from toolbox.distributions.conditional import conditional

rng = default_rng(42)

data = stats.gamma(a=3.0, scale=2.0).rvs(size=50_000, random_state=rng)

rv = fit_moments.fit("gamma", data, ddof=1)
print(rv.mean(), rv.std())

# Zero-inflated normal: P(X=0)=1-p, else Normal(inner_loc, inner_scale)
norm_cond = conditional(stats.norm, name="norm_cond")
x = norm_cond(0.3, 0.0, 1.0).rvs(size=10_000, random_state=rng)
print("zero fraction:", np.mean(x == 0.0))

🧰 Development Setup

Clone and install in editable mode:

git clone https://github.com/michielmj/disco-toolbox.git
cd disco-toolbox
pip install -e ".[dev]"

Run tests:

pytest -q

Type checking:

mypy src

🏗️ Building extensions locally

The toolbox includes two compiled extension modules:

  • toolbox.orderbook._core — C++ / pybind11
  • toolbox.calendar._core — Cython (with optional OpenMP parallelism)

Both are built automatically on install via scikit-build-core.

Typical local build (editable install):

pip install -e ".[dev]"

To enable native CPU optimisations for the Cython extension (local development only):

DISCO_NATIVE_MARCH=1 pip install -e ".[dev]"

If you are modifying C++ or Cython sources and want a clean rebuild:

rm -rf build
pip install -e .

🧾 License

Apache 2.0 License © 2026 — part of the disco-toolbox project.

Metadata

Release files for disco-toolbox 0.0.5

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

Source distribution (sdist)

Source distribution for disco-toolbox 0.0.5
File Size Uploaded Provenance Actions
disco_toolbox-0.0.5.tar.gz 35.3 kB With provenance Details for disco_toolbox-0.0.5.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for disco-toolbox 0.0.5
File Actions
disco_toolbox-0.0.5-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details for disco_toolbox-0.0.5-cp313-cp313-win_amd64.whl
disco_toolbox-0.0.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details for disco_toolbox-0.0.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
disco_toolbox-0.0.5-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details for disco_toolbox-0.0.5-cp313-cp313-macosx_11_0_arm64.whl
disco_toolbox-0.0.5-cp313-cp313-macosx_10_13_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.13+ x86-64 Details for disco_toolbox-0.0.5-cp313-cp313-macosx_10_13_x86_64.whl
disco_toolbox-0.0.5-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details for disco_toolbox-0.0.5-cp312-cp312-win_amd64.whl
disco_toolbox-0.0.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details for disco_toolbox-0.0.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
disco_toolbox-0.0.5-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details for disco_toolbox-0.0.5-cp312-cp312-macosx_11_0_arm64.whl
disco_toolbox-0.0.5-cp312-cp312-macosx_10_13_x86_64.whl CPython 3.12 CPython 3.12 macOS 10.13+ x86-64 Details for disco_toolbox-0.0.5-cp312-cp312-macosx_10_13_x86_64.whl
disco_toolbox-0.0.5-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details for disco_toolbox-0.0.5-cp311-cp311-win_amd64.whl
disco_toolbox-0.0.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details for disco_toolbox-0.0.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
disco_toolbox-0.0.5-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details for disco_toolbox-0.0.5-cp311-cp311-macosx_11_0_arm64.whl
disco_toolbox-0.0.5-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details for disco_toolbox-0.0.5-cp311-cp311-macosx_10_9_x86_64.whl

Total release size: 2.6 MB

Release files / disco_toolbox-0.0.5.tar.gz

Download URL disco_toolbox-0.0.5.tar.gz
Size 35.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ecaafdb6b1c9a4338a695a09a50d5b500b97ee929ad4718f6e4467fcb7a4a466
BLAKE2b-256 checksum
How to use checksums
1a743b0baae86203857db4743bd726c59c8536ab7301d3a00e49c603fbdda779
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp313-cp313-win_amd64.whl

Download URL disco_toolbox-0.0.5-cp313-cp313-win_amd64.whl
Size 179.4 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
36400150b4c7970a8efb69e4a9e745d91c9979641924c35f03dacabd6ed7f35f
BLAKE2b-256 checksum
How to use checksums
fcd5b8156bfc13870420129fe350f0f8360550b81cbc88cb1e3c6b924e4dbc60
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL disco_toolbox-0.0.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 320.6 kB
Tags CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
8521f72dd601cfccba17ba1722c4b1f1c106527232bb36e074eec70c83d29e60
BLAKE2b-256 checksum
How to use checksums
a2bd09a692894e68b2f846e6931f6d68a786044cdb1b46580f6172e082898abe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp313-cp313-macosx_11_0_arm64.whl

Download URL disco_toolbox-0.0.5-cp313-cp313-macosx_11_0_arm64.whl
Size 164.5 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ea320c305c7bac01ccf15b9113f696e596777536278b19f3b7d3ddeeec11f17d
BLAKE2b-256 checksum
How to use checksums
57d78dcb8f390e66bb65ed3b1c2459cb69ebd1465840a525b3701235ca4ff6a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp313-cp313-macosx_10_13_x86_64.whl

Download URL disco_toolbox-0.0.5-cp313-cp313-macosx_10_13_x86_64.whl
Size 178.5 kB
Tags CPython 3.13 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
2c76196cfcf1f5be608763300e0d718d25c67a4bfcef7ec0f458cd38b2e10e95
BLAKE2b-256 checksum
How to use checksums
482dd04aa1aa08db499a389cfdbc4781320395603bcf1b851e2d24b1a9bd108d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp312-cp312-win_amd64.whl

Download URL disco_toolbox-0.0.5-cp312-cp312-win_amd64.whl
Size 179.7 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
4b8614a2fadace4682c94347236e7a9fc67a29225a95c4de6644b888373190e8
BLAKE2b-256 checksum
How to use checksums
b2a5e3b3751942ce506bfd162dce89b8b1c3f11a807594290beaf49c82d07b48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL disco_toolbox-0.0.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 321.0 kB
Tags CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
bd0d480824f3091da74aafa9bca86b97c470b1f252d8c23741f46b5fbf24bb43
BLAKE2b-256 checksum
How to use checksums
47718bbc0023bdb5d1733d480737e6690d6d42bc7ea51d72deae749f5ab48329
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp312-cp312-macosx_11_0_arm64.whl

Download URL disco_toolbox-0.0.5-cp312-cp312-macosx_11_0_arm64.whl
Size 165.0 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1a33a7c209470887c4f99db1940203bfffe52cbd3c1970261bb03caa262a015e
BLAKE2b-256 checksum
How to use checksums
de0c35bf916a66ab1a550b0b6c35e4d44dae20515a3d87df383da579e8db67ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp312-cp312-macosx_10_13_x86_64.whl

Download URL disco_toolbox-0.0.5-cp312-cp312-macosx_10_13_x86_64.whl
Size 179.1 kB
Tags CPython 3.12 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
d2a58a8fb9a3a8f3f6e861365873bb376125e67debac6dde8f528f11015f6491
BLAKE2b-256 checksum
How to use checksums
6baafc05abc3433caf36939a4494fade568c1e2d3985b1cae59bc7806c443e19
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp311-cp311-win_amd64.whl

Download URL disco_toolbox-0.0.5-cp311-cp311-win_amd64.whl
Size 178.6 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
cbed2740b7a94472ab9a7d9c9efb5ba3227e5d726c4bb47ea4b9e1024a6f9159
BLAKE2b-256 checksum
How to use checksums
0b03ad517067f0394e9fb8f0b32f752ccd17954cf7c551e9166f758c878046b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL disco_toolbox-0.0.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 321.4 kB
Tags CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
e5f521d2901c122575ca4bf22215ed88ecb616d354b87f93262176f689722499
BLAKE2b-256 checksum
How to use checksums
1a55a3a25ebabf01d55be0c656df60a2df169792e08876fc924214ad1692ba1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp311-cp311-macosx_11_0_arm64.whl

Download URL disco_toolbox-0.0.5-cp311-cp311-macosx_11_0_arm64.whl
Size 163.5 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
b1a62eaf2b820b717e7193e8756f999a9d1d00ac8d792ed745e6c3948c17c5ad
BLAKE2b-256 checksum
How to use checksums
f3ae5cd1e38216d320629b6262a9cc2a0a84fc5f5b9d50413c3e07a3fe7b19d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Release files / disco_toolbox-0.0.5-cp311-cp311-macosx_10_9_x86_64.whl

Download URL disco_toolbox-0.0.5-cp311-cp311-macosx_10_9_x86_64.whl
Size 176.8 kB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
ebb8f35755dcc1d1558e01f1d23eb9d09504ff76d9dc74e8c81599f75af827ac
BLAKE2b-256 checksum
How to use checksums
03f317fd490dde8ec827ce6e5923830dca8b0bf373300bc5871816c9debf4452
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Apr 7, 2026.

Transparency log

Security for disco-toolbox 0.0.5

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 13 files in this release have been uploaded with provenance metadata.

Select from 13 files

Attestation for disco_toolbox-0.0.5.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 Apr 7, 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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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