Skip to main content

No project description provided

Project description

TinyTiny 3D Engine

A minimalistic 2D/3D engine implemented in Rust and bound to Python, designed to render 3D objects using ASCII art.

Features

  • Rendering Primitives: Supports points, lines, and triangles in both 2D and 3D contexts.
  • ASCII Output: Renders 3D scenes in a charming ASCII art style.
  • Color Shading Support: Renders with RGB colors and shading levels.
  • Materials: Supports 14 materials, including:
    • Texture Mapping: Supports textures up to 256x256 pixels.
    • Double Raster: Allows the use of 2 colors per ASCII character (background and foreground).
    • Perlin Noise: Basic Perlin noise mapped texture.

Setting Up the Development Version

To set up a development version of this engine:

  1. Clone this repository:

    git clone <repo_url>
    
  2. If you have Poetry, run:

    poetry install --with dev --no-root
    

    This will set up the dependencies.

  3. If you don't have Poetry, follow these steps:

    python -m venv .venv
    source .venv/bin/activate
    python -m pip install poetry
    # Now you have Poetry in the virtual environment
    poetry install
    
  4. Compile the Rust version locally:

    maturin develop
    
  5. Run the Rust unit tests:

    cargo test
    
  6. Run the Python unit tests:

    poetry run pytest
    
  7. Check the demo:

    poetry run python demos/3d/some_models.py
    

Tips for Python Path in VSCode

Due to the mix of Python and Rust in this project, the Python code is located in the python folder. More information can be found here.

In launch.json for VSCode:

"env": {"PYTHONPATH": "${workspaceFolder}/python"}

In settings.json:

{
    "python.analysis.extraPaths": [
        "python"
    ]
}

Project details


Download files

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

Source Distribution

tt3de-0.1.0.tar.gz (475.3 kB view hashes)

Uploaded Source

Built Distributions

tt3de-0.1.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl (557.1 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ x86-64

tt3de-0.1.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl (576.1 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ i686

tt3de-0.1.0-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl (654.2 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl (576.9 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARM64

tt3de-0.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (387.7 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (459.1 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

tt3de-0.1.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (430.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (391.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (398.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl (402.1 kB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

tt3de-0.1.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl (558.7 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ x86-64

tt3de-0.1.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl (577.5 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ i686

tt3de-0.1.0-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl (654.0 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl (577.6 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARM64

tt3de-0.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (388.8 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (460.5 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

tt3de-0.1.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (432.7 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (392.1 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (399.5 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl (403.6 kB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

tt3de-0.1.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl (558.6 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ x86-64

tt3de-0.1.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl (576.9 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ i686

tt3de-0.1.0-pp38-pypy38_pp73-musllinux_1_2_armv7l.whl (654.8 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl (577.8 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARM64

tt3de-0.1.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (460.7 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

tt3de-0.1.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (432.4 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (391.8 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (399.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-pp37-pypy37_pp73-musllinux_1_2_x86_64.whl (560.7 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ x86-64

tt3de-0.1.0-pp37-pypy37_pp73-musllinux_1_2_i686.whl (579.0 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ i686

tt3de-0.1.0-pp37-pypy37_pp73-musllinux_1_2_armv7l.whl (656.5 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-pp37-pypy37_pp73-musllinux_1_2_aarch64.whl (580.0 kB view hashes)

Uploaded PyPy musllinux: musl 1.2+ ARM64

tt3de-0.1.0-pp37-pypy37_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (463.1 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

tt3de-0.1.0-pp37-pypy37_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (435.2 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-pp37-pypy37_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (393.8 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (401.5 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp312-none-win_amd64.whl (239.7 kB view hashes)

Uploaded CPython 3.12 Windows x86-64

tt3de-0.1.0-cp312-none-win32.whl (224.2 kB view hashes)

Uploaded CPython 3.12 Windows x86

tt3de-0.1.0-cp312-cp312-musllinux_1_2_x86_64.whl (558.2 kB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

tt3de-0.1.0-cp312-cp312-musllinux_1_2_i686.whl (576.2 kB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

tt3de-0.1.0-cp312-cp312-musllinux_1_2_armv7l.whl (652.4 kB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-cp312-cp312-musllinux_1_2_aarch64.whl (576.8 kB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

tt3de-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (387.4 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (446.4 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x

tt3de-0.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (428.6 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (389.5 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (397.9 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl (401.5 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.5+ i686

tt3de-0.1.0-cp312-cp312-macosx_11_0_arm64.whl (337.4 kB view hashes)

Uploaded CPython 3.12 macOS 11.0+ ARM64

tt3de-0.1.0-cp312-cp312-macosx_10_12_x86_64.whl (342.3 kB view hashes)

Uploaded CPython 3.12 macOS 10.12+ x86-64

tt3de-0.1.0-cp311-none-win_amd64.whl (238.0 kB view hashes)

Uploaded CPython 3.11 Windows x86-64

tt3de-0.1.0-cp311-none-win32.whl (223.9 kB view hashes)

Uploaded CPython 3.11 Windows x86

tt3de-0.1.0-cp311-cp311-musllinux_1_2_x86_64.whl (557.0 kB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

tt3de-0.1.0-cp311-cp311-musllinux_1_2_i686.whl (574.4 kB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

tt3de-0.1.0-cp311-cp311-musllinux_1_2_armv7l.whl (652.9 kB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-cp311-cp311-musllinux_1_2_aarch64.whl (576.1 kB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

tt3de-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (386.7 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (454.3 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x

tt3de-0.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (428.7 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (390.4 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (397.5 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl (401.5 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.5+ i686

tt3de-0.1.0-cp311-cp311-macosx_11_0_arm64.whl (336.4 kB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

tt3de-0.1.0-cp311-cp311-macosx_10_12_x86_64.whl (341.7 kB view hashes)

Uploaded CPython 3.11 macOS 10.12+ x86-64

tt3de-0.1.0-cp310-none-win_amd64.whl (238.0 kB view hashes)

Uploaded CPython 3.10 Windows x86-64

tt3de-0.1.0-cp310-none-win32.whl (224.2 kB view hashes)

Uploaded CPython 3.10 Windows x86

tt3de-0.1.0-cp310-cp310-musllinux_1_2_x86_64.whl (556.7 kB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

tt3de-0.1.0-cp310-cp310-musllinux_1_2_i686.whl (574.4 kB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

tt3de-0.1.0-cp310-cp310-musllinux_1_2_armv7l.whl (652.1 kB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-cp310-cp310-musllinux_1_2_aarch64.whl (576.8 kB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

tt3de-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (386.2 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (454.9 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x

tt3de-0.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (428.8 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (389.7 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (397.2 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl (401.4 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.5+ i686

tt3de-0.1.0-cp310-cp310-macosx_11_0_arm64.whl (336.4 kB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

tt3de-0.1.0-cp39-none-win_amd64.whl (238.5 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

tt3de-0.1.0-cp39-none-win32.whl (224.7 kB view hashes)

Uploaded CPython 3.9 Windows x86

tt3de-0.1.0-cp39-cp39-musllinux_1_2_x86_64.whl (557.4 kB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

tt3de-0.1.0-cp39-cp39-musllinux_1_2_i686.whl (576.7 kB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

tt3de-0.1.0-cp39-cp39-musllinux_1_2_armv7l.whl (653.9 kB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-cp39-cp39-musllinux_1_2_aarch64.whl (577.1 kB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

tt3de-0.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (387.2 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (455.8 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x

tt3de-0.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (430.3 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (391.0 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (397.4 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl (403.3 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.5+ i686

tt3de-0.1.0-cp39-cp39-macosx_11_0_arm64.whl (336.3 kB view hashes)

Uploaded CPython 3.9 macOS 11.0+ ARM64

tt3de-0.1.0-cp38-none-win_amd64.whl (237.0 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

tt3de-0.1.0-cp38-none-win32.whl (223.4 kB view hashes)

Uploaded CPython 3.8 Windows x86

tt3de-0.1.0-cp38-cp38-musllinux_1_2_x86_64.whl (557.3 kB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

tt3de-0.1.0-cp38-cp38-musllinux_1_2_i686.whl (575.8 kB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

tt3de-0.1.0-cp38-cp38-musllinux_1_2_armv7l.whl (651.9 kB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-cp38-cp38-musllinux_1_2_aarch64.whl (576.3 kB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

tt3de-0.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (385.8 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (456.6 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x

tt3de-0.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (428.5 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (390.0 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (396.6 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl (402.0 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.5+ i686

tt3de-0.1.0-cp37-none-win_amd64.whl (237.4 kB view hashes)

Uploaded CPython 3.7 Windows x86-64

tt3de-0.1.0-cp37-none-win32.whl (222.7 kB view hashes)

Uploaded CPython 3.7 Windows x86

tt3de-0.1.0-cp37-cp37m-musllinux_1_2_x86_64.whl (557.0 kB view hashes)

Uploaded CPython 3.7m musllinux: musl 1.2+ x86-64

tt3de-0.1.0-cp37-cp37m-musllinux_1_2_i686.whl (575.8 kB view hashes)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

tt3de-0.1.0-cp37-cp37m-musllinux_1_2_armv7l.whl (653.1 kB view hashes)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARMv7l

tt3de-0.1.0-cp37-cp37m-musllinux_1_2_aarch64.whl (576.0 kB view hashes)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

tt3de-0.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (386.0 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

tt3de-0.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl (455.8 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ s390x

tt3de-0.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (429.6 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ppc64le

tt3de-0.1.0-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (390.1 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARMv7l

tt3de-0.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (396.8 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

tt3de-0.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl (402.3 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.5+ i686

Supported by

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