Skip to main content

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

Project description

Image for: Project description

Ruff

Docs | Playground

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

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

Image for: 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

Image for: 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

Image for: 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.11.13/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.11.13/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.11.13
  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

Image for: 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

Image for: Contributing

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

You can also join us on Discord.

Support

Image for: 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

Image for: 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?

Image for: 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

Image for: License

This repository is licensed under the MIT License

Project details

Image for: Project details

Release history Release notifications | RSS feed

Image for: Release history Release notifications | RSS feed

Download files

Image for: 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.11.13.tar.gz (4.3 MB view details)

Uploaded Source

Built Distributions

ruff-0.11.13-py3-none-win_arm64.whl (10.7 MB view details)

Uploaded Python 3 Windows ARM64

ruff-0.11.13-py3-none-win_amd64.whl (11.5 MB view details)

Uploaded Python 3 Windows x86-64

ruff-0.11.13-py3-none-win32.whl (10.5 MB view details)

Uploaded Python 3 Windows x86

ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl (11.6 MB view details)

Uploaded Python 3 musllinux: musl 1.2+ x86-64

ruff-0.11.13-py3-none-musllinux_1_2_i686.whl (11.1 MB view details)

Uploaded Python 3 musllinux: musl 1.2+ i686

ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl (10.1 MB view details)

Uploaded Python 3 musllinux: musl 1.2+ ARMv7l

ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl (10.5 MB view details)

Uploaded Python 3 musllinux: musl 1.2+ ARM64

ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.6 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ x86-64

ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (11.3 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ s390x

ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (12.1 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ppc64le

ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (12.5 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ppc64

ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (11.7 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ i686

ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (10.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (10.6 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

ruff-0.11.13-py3-none-macosx_11_0_arm64.whl (10.4 MB view details)

Uploaded Python 3 macOS 11.0+ ARM64

ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl (11.1 MB view details)

Uploaded Python 3 macOS 10.12+ x86-64

ruff-0.11.13-py3-none-linux_armv6l.whl (10.3 MB view details)

Uploaded Python 3

File details

Image for: File details

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

File metadata

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

File hashes

Hashes for ruff-0.11.13.tar.gz
Algorithm Hash digest
SHA256 26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514
MD5 60c8115a2e30b037b1520933c3bf346b
BLAKE2b-256 edda9c6f995903b4d9474b39da91d2d626659af3ff1eeb43e9ae7c119349dba6

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b
MD5 3ceac23c4629f1fec09f0f32c9af1dbe
BLAKE2b-256 ecbfb273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3
MD5 206267b1bb7b6a2bc65a9e27ef665c4d
BLAKE2b-256 46f47c27734ac2073aae8efb0119cae6931b6fb48017adf048fdf85c19337afc

See more details on using hashes here.

File details

Image for: File details

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

File metadata

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

File hashes

Hashes for ruff-0.11.13-py3-none-win32.whl
Algorithm Hash digest
SHA256 96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250
MD5 fab4ad9fc28ca661b37f8954ad64ca67
BLAKE2b-256 7c91263e33ab93ab09ca06ce4f8f8547a858cc198072f873ebc9be7466790bae

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492
MD5 81cf5d5e8b1918562b048b26536a9cf8
BLAKE2b-256 5ac0b0b508193b0e8a1654ec683ebab18d309861f8bd64e3a2f9648b80d392cb

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432
MD5 7896c7f2d559411df13a8e8341e058a1
BLAKE2b-256 f48e39a094af6967faa57ecdeacb91bedfb232474ff8c3d20f16a5514e6b3534

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7
MD5 b2f9bb3b89d93b028d7dca22c62e8afa
BLAKE2b-256 5adc195e6f17d7b3ea6b12dc4f3e9de575db7983db187c378d44606e5d503319

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc
MD5 440f96c8ca8f322c71811692df689ebf
BLAKE2b-256 5dd43d580c616316c7f07fb3c99dbecfe01fbaea7b6fd9a82b801e72e5de742a

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9
MD5 f54a85a3bedc75899a2d778deb57f767
BLAKE2b-256 75f0782e7d681d660eda8c536962920c41309e6dd4ebcea9a2714ed5127d44bd

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71
MD5 54a447e258adb18cd0d954dfcb557192
BLAKE2b-256 5d2ccaaeda564cbe103bed145ea557cb86795b18651b0f6b3ff6a10e84e5a33f

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165
MD5 8d7a26384340dce02f964b4db01da709
BLAKE2b-256 170ecefe778b46dbd0cbcb03a839946c8f80a06f7968eb298aa4d1a4293f3448

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933
MD5 f40b9753c34521ad1dd4ab22597f660b
BLAKE2b-256 bbf0466fe8469b85c561e081d798c45f8a1d21e0b4a5ef795a1d7f1a9a9ec182

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629
MD5 b69fe8150e0c738582c8fb3ac47ee55b
BLAKE2b-256 f310e2e62f77c65ede8cd032c2ca39c41f48feabedb6e282bfd6073d81bb671d

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc
MD5 acd829445304325901896883dda88c29
BLAKE2b-256 6c9cb4c2acf24ea4426016d511dfdc787f4ce1ceb835f3c5fbdbcb32b1c63bda

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a
MD5 2ec0fdb719e81f3cb86db268806f6b69
BLAKE2b-256 8b5bf6d94f2980fa1ee854b41568368a2e1252681b9238ab2895e133d303538f

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b
MD5 85cbf0de444ec01d92f9d58c0cd1300f
BLAKE2b-256 7779d8cec175856ff810a19825d09ce700265f905c643c69f45d2b737e4a470a

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48
MD5 4a9294dc52d993f551d7b1d5f29bb971
BLAKE2b-256 78db87c3b59b0d4e753e40b6a3b4a2642dfd1dcaefbff121ddc64d6c8b47ba00

See more details on using hashes here.

File details

Image for: File details

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

File metadata

File hashes

Hashes for ruff-0.11.13-py3-none-linux_armv6l.whl
Algorithm Hash digest
SHA256 4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46
MD5 8498389a78540204a0aeb6fb02669fe8
BLAKE2b-256 7dcea11d381192966e0b4290842cc8d4fac7dc9214ddf627c11c1afff87da29b

See more details on using hashes here.

Supported by

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