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:

pip install ruff

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.4.9
  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 alongside any other editor through the Ruff LSP.

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: chartboost/ruff-action@v1

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.8
target-version = "py38"

[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.4.9.tar.gz (2.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.4.9-py3-none-win_arm64.whl (8.0 MB view details)

Uploaded Python 3Windows ARM64

ruff-0.4.9-py3-none-win_amd64.whl (8.6 MB view details)

Uploaded Python 3Windows x86-64

ruff-0.4.9-py3-none-win32.whl (7.8 MB view details)

Uploaded Python 3Windows x86

ruff-0.4.9-py3-none-musllinux_1_2_x86_64.whl (8.9 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ruff-0.4.9-py3-none-musllinux_1_2_i686.whl (8.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

ruff-0.4.9-py3-none-musllinux_1_2_armv7l.whl (7.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

ruff-0.4.9-py3-none-musllinux_1_2_aarch64.whl (8.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ruff-0.4.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

ruff-0.4.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (10.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ s390x

ruff-0.4.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (9.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

ruff-0.4.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (9.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64

ruff-0.4.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (8.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ i686

ruff-0.4.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

ruff-0.4.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (8.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.4.9-py3-none-macosx_11_0_arm64.whl (8.2 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

ruff-0.4.9-py3-none-macosx_10_12_x86_64.whl (8.5 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: ruff-0.4.9.tar.gz
  • Upload date:
  • Size: 2.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9.tar.gz
Algorithm Hash digest
SHA256 f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3
MD5 29a9b3044a81185a1a53e06059e4d4e3
BLAKE2b-256 8153e4e59acfc403dc93f0374f46244dd70e192d89620d6a28ca99f007b22d24

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-win_arm64.whl
  • Upload date:
  • Size: 8.0 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 5d5460f789ccf4efd43f265a58538a2c24dbce15dbf560676e430375f20a8198
MD5 1fd8ddb95ad39f810360c986b542f01c
BLAKE2b-256 119b83e4ee4825cb66a724dd20aefda7d628cd56148fe1153feea513a3e8c53a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-win_amd64.whl
  • Upload date:
  • Size: 8.6 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 e0a22c4157e53d006530c902107c7f550b9233e9706313ab57b892d7197d8e52
MD5 cf2ffedf56e14ae85841cadb676eea2e
BLAKE2b-256 cdb23ac36982ae94cb78bfea85b79fbc868c9d2fb68bbbabf1e85ca9a9b2ba9a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-win32.whl
  • Upload date:
  • Size: 7.8 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-win32.whl
Algorithm Hash digest
SHA256 8064590fd1a50dcf4909c268b0e7c2498253273309ad3d97e4a752bb9df4f521
MD5 c82278d483d4c78ca29bc6925a45db62
BLAKE2b-256 7958c4672c1d0debd608a1a00d395a5071ebeb519fdf0068f02e8fcfd490e0c4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 8.9 MB
  • Tags: Python 3, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 732dd550bfa5d85af8c3c6cbc47ba5b67c6aed8a89e2f011b908fc88f87649db
MD5 f3c62f32e510751a6b9d69d59c701577
BLAKE2b-256 8c18c9d717a0be15ca5aee55e918fe02a8dfca92a756a02b809671576f2920d8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-musllinux_1_2_i686.whl
  • Upload date:
  • Size: 8.4 MB
  • Tags: Python 3, musllinux: musl 1.2+ i686
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 784d3ec9bd6493c3b720a0b76f741e6c2d7d44f6b2be87f5eef1ae8cc1d54c84
MD5 22ae62e737e6bcac0ed01a08e57a5aae
BLAKE2b-256 b078b51631276d0db7ec9fe32490e6bc9206a3f670abc4a0ffeecdeeb0d45ac4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-musllinux_1_2_armv7l.whl
  • Upload date:
  • Size: 7.6 MB
  • Tags: Python 3, musllinux: musl 1.2+ ARMv7l
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 8c1aff58c31948cc66d0b22951aa19edb5af0a3af40c936340cd32a8b1ab7438
MD5 7705f11e36a8acc4fc94feefbf202f4a
BLAKE2b-256 dc7a5b2eebe8efd89f210b8fb8ad36af35fa9163cc38c2f34e1c13baa92433d4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 673bddb893f21ab47a8334c8e0ea7fd6598ecc8e698da75bcd12a7b9d0a3206e
MD5 5927c6ce2bc7461f375c336f74b40693
BLAKE2b-256 1ec88377e4a8677531805f081e5bc659dd7b24d780d2b628bde4904f0b98e658

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 88bffe9c6a454bf8529f9ab9091c99490578a593cc9f9822b7fc065ee0712a06
MD5 6dcf5a5b3386400f209ef3b635b21d0f
BLAKE2b-256 d32f3a63f461895201c6836f7822f29ada06d9cbd4b506b152f1d2800c917853

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893
MD5 5049136ff1b95ad8c8eeeaeb3ad9c13a
BLAKE2b-256 ab0a9bd8a497aa874c32f3da7ed597a4c0c1853d745d26ea02a759d45d78f271

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 78de3fdb95c4af084087628132336772b1c5044f6e710739d440fc0bccf4d321
MD5 1b75f981213cd2f2107a80e8b586b703
BLAKE2b-256 8cf4ddd5645482d3a434129b90f3cbc86155ffbdfa356a43ac34a328dda70189

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 2d45ddc6d82e1190ea737341326ecbc9a61447ba331b0a8962869fcada758505
MD5 619202ae3480aa74b476613f13f64c51
BLAKE2b-256 b74a2adfbbf5268a23c4242f5e531bd52cf98647e3d3de15ed34722189892ac2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff
MD5 38cd71c61b957b683e492a42192b4779
BLAKE2b-256 5710bbffdc8e52b8711ee2c4570ce694f7adbd74a7f8eb2f31362e732cb60515

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde
MD5 aa3177abdc4e613822a6e2833f35e929
BLAKE2b-256 9893f031fc6dba56aba9aa22883e812b3cb16dc1dc6709fdbe20be738e31a724

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4555056049d46d8a381f746680db1c46e67ac3b00d714606304077682832998e
MD5 33016cd60cd28d2b30fcd664ab54f66f
BLAKE2b-256 02da0500bbfbe41f6d94fb7307a3235e3f0759ec2e6d77180b6f8b80ea887d7b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.4.9-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 8.2 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.4

File hashes

Hashes for ruff-0.4.9-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 98ec2775fd2d856dc405635e5ee4ff177920f2141b8e2d9eb5bd6efd50e80317
MD5 41766cb94855f004c05ab064f6ab7169
BLAKE2b-256 170e2d7d11d34aa78427f19aaa40b2e2cf5d110dd66fab11106a4a316f4a159d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.4.9-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b262ed08d036ebe162123170b35703aaf9daffecb698cd367a8d585157732991
MD5 43ac1365a8ff68e9506c08335bc62639
BLAKE2b-256 190ecacefb59c6a7dd2bd1de5640902e2e690e52c11c2140f9fa93f764293e27

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