Skip to main content

An extremely fast Python linter and code formatter, written in Rust.

Project description

Ruff

Ruff image image image Actions status Discord

Docs | Playground

An extremely fast Python linter and code formatter, written in Rust.

Shows a bar chart with benchmark results.

Linting the CPython codebase from scratch.

  • ⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black)
  • 🐍 Installable via pip
  • 🛠️ pyproject.toml support
  • 🤝 Python 3.13 compatibility
  • ⚖️ Drop-in parity with Flake8, isort, and Black
  • 📦 Built-in caching, to avoid re-analyzing unchanged files
  • 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports)
  • 📏 Over 800 built-in rules, with native re-implementations of popular Flake8 plugins, like flake8-bugbear
  • ⌨️ First-party editor integrations for VS Code and more
  • 🌎 Monorepo-friendly, with hierarchical and cascading configuration

Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface.

Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.

Ruff is extremely actively developed and used in major open-source projects like:

...and many more.

Ruff is backed by Astral. Read the launch post, or the original project announcement.

Testimonials

Sebastián Ramírez, creator of FastAPI:

Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.

Nick Schrock, founder of Elementl, co-creator of GraphQL:

Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4 cores on my M1. Running ruff against our entire codebase takes .4 seconds.

Bryan Van de Ven, co-creator of Bokeh, original author of Conda:

Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added it as an actual commit hook, which is terrific.

Timothy Crosley, creator of isort:

Just switched my first project to Ruff. Only one downside so far: it's so fast I couldn't believe it was working till I intentionally introduced some errors.

Tim Abbott, lead developer of Zulip:

This is just ridiculously fast... ruff is amazing.

Table of Contents

For more, see the documentation.

  1. Getting Started
  2. Configuration
  3. Rules
  4. Contributing
  5. Support
  6. Acknowledgements
  7. Who's Using Ruff?
  8. License

Getting Started

For more, see the documentation.

Installation

Ruff is available as ruff on PyPI.

Invoke Ruff directly with uvx:

uvx ruff check   # Lint all files in the current directory.
uvx ruff format  # Format all files in the current directory.

Or install Ruff with uv (recommended), pip, or pipx:

# With uv.
uv tool install ruff@latest  # Install Ruff globally.
uv add --dev ruff            # Or add Ruff to your project.

# With pip.
pip install ruff

# With pipx.
pipx install ruff

Starting with version 0.5.0, Ruff can be installed with our standalone installers:

# On macOS and Linux.
curl -LsSf https://astral.sh/ruff/install.sh | sh

# On Windows.
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"

# For a specific version.
curl -LsSf https://astral.sh/ruff/0.9.4/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.9.4/install.ps1 | iex"

You can also install Ruff via Homebrew, Conda, and with a variety of other package managers.

Usage

To run Ruff as a linter, try any of the following:

ruff check                          # Lint all files in the current directory (and any subdirectories).
ruff check path/to/code/            # Lint all files in `/path/to/code` (and any subdirectories).
ruff check path/to/code/*.py        # Lint all `.py` files in `/path/to/code`.
ruff check path/to/code/to/file.py  # Lint `file.py`.
ruff check @arguments.txt           # Lint using an input file, treating its contents as newline-delimited command-line arguments.

Or, to run Ruff as a formatter:

ruff format                          # Format all files in the current directory (and any subdirectories).
ruff format path/to/code/            # Format all files in `/path/to/code` (and any subdirectories).
ruff format path/to/code/*.py        # Format all `.py` files in `/path/to/code`.
ruff format path/to/code/to/file.py  # Format `file.py`.
ruff format @arguments.txt           # Format using an input file, treating its contents as newline-delimited command-line arguments.

Ruff can also be used as a pre-commit hook via ruff-pre-commit:

- repo: https://github.com/astral-sh/ruff-pre-commit
  # Ruff version.
  rev: v0.9.4
  hooks:
    # Run the linter.
    - id: ruff
      args: [ --fix ]
    # Run the formatter.
    - id: ruff-format

Ruff can also be used as a VS Code extension or with various other editors.

Ruff can also be used as a GitHub Action via ruff-action:

name: Ruff
on: [ push, pull_request ]
jobs:
  ruff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/ruff-action@v3

Configuration

Ruff can be configured through a pyproject.toml, ruff.toml, or .ruff.toml file (see: Configuration, or Settings for a complete list of all configuration options).

If left unspecified, Ruff's default configuration is equivalent to the following ruff.toml file:

# Exclude a variety of commonly ignored directories.
exclude = [
    ".bzr",
    ".direnv",
    ".eggs",
    ".git",
    ".git-rewrite",
    ".hg",
    ".ipynb_checkpoints",
    ".mypy_cache",
    ".nox",
    ".pants.d",
    ".pyenv",
    ".pytest_cache",
    ".pytype",
    ".ruff_cache",
    ".svn",
    ".tox",
    ".venv",
    ".vscode",
    "__pypackages__",
    "_build",
    "buck-out",
    "build",
    "dist",
    "node_modules",
    "site-packages",
    "venv",
]

# Same as Black.
line-length = 88
indent-width = 4

# Assume Python 3.9
target-version = "py39"

[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`)  codes by default.
select = ["E4", "E7", "E9", "F"]
ignore = []

# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[format]
# Like Black, use double quotes for strings.
quote-style = "double"

# Like Black, indent with spaces, rather than tabs.
indent-style = "space"

# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false

# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

Note that, in a pyproject.toml, each section header should be prefixed with tool.ruff. For example, [lint] should be replaced with [tool.ruff.lint].

Some configuration options can be provided via dedicated command-line arguments, such as those related to rule enablement and disablement, file discovery, and logging level:

ruff check --select F401 --select F403 --quiet

The remaining configuration options can be provided through a catch-all --config argument:

ruff check --config "lint.per-file-ignores = {'some_file.py' = ['F841']}"

To opt in to the latest lint rules, formatter style changes, interface updates, and more, enable preview mode by setting preview = true in your configuration file or passing --preview on the command line. Preview mode enables a collection of unstable features that may change prior to stabilization.

See ruff help for more on Ruff's top-level commands, or ruff help check and ruff help format for more on the linting and formatting commands, respectively.

Rules

Ruff supports over 800 lint rules, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature.

By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

If you're just getting started with Ruff, the default rule set is a great place to start: it catches a wide variety of common errors (like unused imports) with zero configuration.

Beyond the defaults, Ruff re-implements some of the most popular Flake8 plugins and related code quality tools, including:

For a complete enumeration of the supported rules, see Rules.

Contributing

Contributions are welcome and highly appreciated. To get started, check out the contributing guidelines.

You can also join us on Discord.

Support

Having trouble? Check out the existing issues on GitHub, or feel free to open a new one.

You can also ask for help on Discord.

Acknowledgements

Ruff's linter draws on both the APIs and implementation details of many other tools in the Python ecosystem, especially Flake8, Pyflakes, pycodestyle, pydocstyle, pyupgrade, and isort.

In some cases, Ruff includes a "direct" Rust port of the corresponding tool. We're grateful to the maintainers of these tools for their work, and for all the value they've provided to the Python community.

Ruff's formatter is built on a fork of Rome's rome_formatter, and again draws on both API and implementation details from Rome, Prettier, and Black.

Ruff's import resolver is based on the import resolution algorithm from Pyright.

Ruff is also influenced by a number of tools outside the Python ecosystem, like Clippy and ESLint.

Ruff is the beneficiary of a large number of contributors.

Ruff is released under the MIT license.

Who's Using Ruff?

Ruff is used by a number of major open-source projects and companies, including:

Show Your Support

If you're using Ruff, consider adding the Ruff badge to your project's README.md:

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

...or README.rst:

.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
    :target: https://github.com/astral-sh/ruff
    :alt: Ruff

...or, as HTML:

<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>

License

This repository is licensed under the MIT License

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

ruff-0.9.4.tar.gz (3.6 MB view details)

Uploaded Source

Built Distributions

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

ruff-0.9.4-py3-none-win_arm64.whl (10.1 MB view details)

Uploaded Python 3Windows ARM64

ruff-0.9.4-py3-none-win_amd64.whl (10.9 MB view details)

Uploaded Python 3Windows x86-64

ruff-0.9.4-py3-none-win32.whl (9.9 MB view details)

Uploaded Python 3Windows x86

ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl (12.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ruff-0.9.4-py3-none-musllinux_1_2_i686.whl (12.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl (11.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl (11.9 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (14.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ s390x

ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (12.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (13.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64

ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (12.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ i686

ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (11.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (11.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.9.4-py3-none-macosx_11_0_arm64.whl (11.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl (11.6 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

ruff-0.9.4-py3-none-linux_armv6l.whl (11.7 MB view details)

Uploaded Python 3

File details

Details for the file ruff-0.9.4.tar.gz.

File metadata

  • Download URL: ruff-0.9.4.tar.gz
  • Upload date:
  • Size: 3.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.25

File hashes

Hashes for ruff-0.9.4.tar.gz
Algorithm Hash digest
SHA256 6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7
MD5 a5ca743175216018cee06db9ca38ae2a
BLAKE2b-256 c017529e78f49fc6f8076f50d985edd9a2cf011d1dbadb1cdeacc1d12afc1d26

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-win_arm64.whl.

File metadata

  • Download URL: ruff-0.9.4-py3-none-win_arm64.whl
  • Upload date:
  • Size: 10.1 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.25

File hashes

Hashes for ruff-0.9.4-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41
MD5 50bf77866b688cbf7ceb7cf8b329bd19
BLAKE2b-256 c6e63d6ec3bc3d254e7f005c543a661a41c3e788976d0e52a1ada195bd664344

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-win_amd64.whl.

File metadata

  • Download URL: ruff-0.9.4-py3-none-win_amd64.whl
  • Upload date:
  • Size: 10.9 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.25

File hashes

Hashes for ruff-0.9.4-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e
MD5 0aa26ca5c594558aa365d35522b9ab74
BLAKE2b-256 12412d2d2c6a72e62566f730e49254f602dfed23019c33b5b21ea8f8917315a1

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-win32.whl.

File metadata

  • Download URL: ruff-0.9.4-py3-none-win32.whl
  • Upload date:
  • Size: 9.9 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.25

File hashes

Hashes for ruff-0.9.4-py3-none-win32.whl
Algorithm Hash digest
SHA256 db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402
MD5 a225f76143b7a6a90217197f1cbb09de
BLAKE2b-256 2315f6751c07c21ca10e3f4a51ea495ca975ad936d780c347d9808bcedbd7182

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0
MD5 17d1aa456bc4e9dacff67a571587ef31
BLAKE2b-256 3d8c893fa9551760b2f8eb2a351b603e96f15af167ceaf27e27ad873570bc04c

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c
MD5 e20bdac14f28e0ea0e623d65c3896c26
BLAKE2b-256 185930490e483e804ccaa8147dd78c52e44ff96e1c30b5a95d69a63163cdb15b

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6
MD5 3fb92cf8458ccea160d0c9196e0101a8
BLAKE2b-256 d6f49c8499ae8426da48363bbb78d081b817b0f64a9305f9b7f87eab2a8fb2c1

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b
MD5 f42ac8f127eebec476dfa82b4db5a599
BLAKE2b-256 34cbf5d50d0c4ecdcc7670e348bd0b11878154bc4617f3fdd1e8ad5297c0d0ba

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231
MD5 b8dac23827e2858ca7fd07c586b705ad
BLAKE2b-256 30246200b13ea611b83260501b6955b764bb320e23b2b75884c60ee7d3f0b68e

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214
MD5 0ccef8a7aa11ede30a22d57d0d479ac8
BLAKE2b-256 c7175f1971e54bd71604da6788efd84d66d789362b1105e17e5ccc53bba0289b

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a
MD5 148df1498f4ba583c9a93db475d4d04e
BLAKE2b-256 5fc3ad2dd59d3cabbc12df308cced780f9c14367f0321e7800ca0fe52849da4c

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b
MD5 2ca31831d9fabf0ab19a7ade2f8b4dfe
BLAKE2b-256 0eccdadb9b35473d7cb17c7ffe4737b4377aeec519a446ee8514123ff4a26091

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec
MD5 ea692bfa863bd615400b00ee0408772f
BLAKE2b-256 c0967915a7c6877bb734caa6a2af424045baf6419f685632469643dbd8eb2958

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e
MD5 f7bde515c9babac1b9e572b4115dadf1
BLAKE2b-256 79d1757559995c8ba5f14dfec4459ef2dd3fcea82ac43bc4e7c7bf47484180c0

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137
MD5 0def64a9fbf6819ad9c5ad3a61b2bffb
BLAKE2b-256 9e673660d58e893d470abb9a13f679223368ff1684a4ef40f254a0157f51b448

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b
MD5 202c88b456978bdeb8cc074a6cbe97be
BLAKE2b-256 dcd7cd822437561082f1c9d7225cc0d0fbb4bad117ad7ac3c41cd5d7f0fa948c

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf
MD5 12d5f60360d9e750f438a20043a56b82
BLAKE2b-256 2ea62efa772d335da48a70ab2c6bb41a096c8517ca43c086ea672d51079e3d1f

See more details on using hashes here.

File details

Details for the file ruff-0.9.4-py3-none-linux_armv6l.whl.

File metadata

File hashes

Hashes for ruff-0.9.4-py3-none-linux_armv6l.whl
Algorithm Hash digest
SHA256 64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706
MD5 5385b869614d736f0af0a8d4370a9a50
BLAKE2b-256 b6f83fafb7804d82e0699a122101b5bee5f0d6e17c3a806dcbc527bb7d3f5b7a

See more details on using hashes here.

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