Skip to main content

Python bindings for the Y-CRDT built from yrs (Rust)

Project description

PyPI version

Ypy

Ypy is a Python binding for Y-CRDT. It provides distributed data types that enable real-time collaboration between devices. Ypy can sync data with any other platform that has a Y-CRDT binding, allowing for seamless cross-domain communication. The library is a thin wrapper around Yrs, taking advantage of the safety and performance of Rust.

We are looking for a maintainer 👀

Installation

pip install y-py

Getting Started

Ypy provides many of the same shared data types as Yjs. All objects are shared within a YDoc and get modified within a transaction block.

import y_py as Y

d1 = Y.YDoc()
# Create a new YText object in the YDoc
text = d1.get_text('test')
# Start a transaction in order to update the text
with d1.begin_transaction() as txn:
    # Add text contents
    text.extend(txn, "hello world!")

# Create another document
d2 = Y.YDoc()
# Share state with the original document
state_vector = Y.encode_state_vector(d2)
diff = Y.encode_state_as_update(d1, state_vector)
Y.apply_update(d2, diff)

value = str(d2.get_text('test'))

assert value == "hello world!"

Development Setup

  1. Install Rust and Python
  2. Install maturin in order to build Ypy: pip install maturin
  3. Create a development build of the library: maturin develop

Tests

All tests are located in /tests. To run the tests, install pytest and run the command line tool from the project root:

pip install pytest
pytest

Using Hatch

If you are using hatch, there is a test environment matrix defined in pyproject.toml that will run commands in virtual environments for py37 through py312.

hatch run test:maturin develop
hatch run test:pytest

Build Ypy

Build the library as a wheel and store them in target/wheels:

maturin build

Ypy in WASM (Pyodide)

As a Rust-based library, Ypy cannot build "pure Python" wheels. CI processes build and upload a number of wheels to PyPI, but PyPI does not support hosting emscripten / wasm32 wheels necessary to import in Pyodide (see https://github.com/pypi/warehouse/issues/10416 for more info and updates). For now, Ypy will build emscripten wheels and attach the binaries as assets in the appropriate Releases entry. Unfortunately, trying to install directly from the Github download link will result in a CORS error, so you'll need to use a proxy to pull in the binary and write / install from emscripten file system or host the binary somewhere that is CORS accessible for your application.

You can try out Ypy in Pyodide using the terminal emulator at pyodide.org:

Welcome to the Pyodide terminal emulator 🐍
Python 3.10.2 (main, Sep 15 2022 23:28:12) on WebAssembly/Emscripten
Type "help", "copyright", "credits" or "license" for more information.
>>> wheel_url = 'https://github.com/y-crdt/ypy/releases/download/v0.5.5/y_py-0.5.5-cp310-cp310-emscripten_3_1_14_wasm32.whl'
>>> wheel_name = wheel_url.split('/')[-1]
>>> wheel_name
'y_py-0.5.5-cp310-cp310-emscripten_3_1_14_wasm32.whl'
>>> 
>>> proxy_url = f'https://api.allorigins.win/raw?url={wheel_url}'
>>> proxy_url
'https://api.allorigins.win/raw?url=https://github.com/y-crdt/ypy/releases/download/v0.5.5/y_py-0.5.5-cp310-cp310-emscripten_3_1_14_wasm32.whl'
>>> 
>>> import pyodide
>>> resp = await pyodide.http.pyfetch(proxy_url)
>>> resp.status
200
>>> 
>>> content = await resp.bytes()
>>> len(content)
360133
>>> content[:50]
b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xae\xb2}U\x92l\xa7E\xe6\x04\x00\x00u\t\x00\x00\x1d\x00\x00\x00y_py-0.5.5.dist-info'
>>>
>>> with open(wheel_name, 'wb') as f:
...   f.write(content)
... 
360133
>>> 
>>> import micropip
>>> await micropip.install(f'emfs:./{wheel_name}')
>>> 
>>> import y_py as Y
>>> Y
<module 'y_py' from '/lib/python3.10/site-packages/y_py/__init__.py'>
>>> 
>>> d1 = Y.YDoc()
>>> text = d1.get_text('test')
>>> with d1.begin_transaction() as txn:
    text.extend(txn, "hello world!")
... 
>>> d2 = Y.YDoc()
>>> state_vector = Y.encode_state_vector(d2)
>>> diff = Y.encode_state_as_update(d1, state_vector)
>>> Y.apply_update(d2, diff)
>>> d2.get_text('test')
YText(hello world!)

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

y_py_dart-0.6.3a20.tar.gz (59.2 kB view details)

Uploaded Source

Built Distributions

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

y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (873.8 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (936.5 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ s390x

y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.0 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ppc64le

y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (879.3 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARMv7l

y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (864.3 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

y_py_dart-0.6.3a20-pp39-pypy39_pp73-macosx_10_12_x86_64.whl (808.1 kB view details)

Uploaded PyPymacOS 10.12+ x86-64

y_py_dart-0.6.3a20-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.6 MB view details)

Uploaded PyPymacOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (873.9 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (936.1 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ s390x

y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.0 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ppc64le

y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (878.7 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARMv7l

y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (863.4 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

y_py_dart-0.6.3a20-pp38-pypy38_pp73-macosx_10_12_x86_64.whl (808.5 kB view details)

Uploaded PyPymacOS 10.12+ x86-64

y_py_dart-0.6.3a20-pp38-pypy38_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.6 MB view details)

Uploaded PyPymacOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (871.7 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl (932.4 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ s390x

y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.0 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ppc64le

y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (877.6 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARMv7l

y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (863.0 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

y_py_dart-0.6.3a20-cp38-abi3-macosx_10_12_x86_64.whl (806.2 kB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

y_py_dart-0.6.3a20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (1.6 MB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file y_py_dart-0.6.3a20.tar.gz.

File metadata

  • Download URL: y_py_dart-0.6.3a20.tar.gz
  • Upload date:
  • Size: 59.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for y_py_dart-0.6.3a20.tar.gz
Algorithm Hash digest
SHA256 b37c599bd979623badb82fd7f72d03af1190aca907930fd2b828e03594f8ddec
MD5 2f4575cd2b36d045566dceb1ce006116
BLAKE2b-256 ed28ed8053522793b7a18ab3f099bc45d4bf5b1fa02f288497a1f7df07d45fc2

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 61fbf5a992de7733e99b73928adea5c46cf107f49d88f1494fb4cee3374cd96a
MD5 8e656490b22a0997b3a0740291981813
BLAKE2b-256 ed9fb306751413f57f0db79a7c291369ad3caacdb85855dec5a1514b66be9b91

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 96c470f4bc6d94889b0b528f45ad05889142988ddf97e9bed34fce13b491f71d
MD5 cff0e624662cf58c45a7b8626dad6df9
BLAKE2b-256 a01719362908bc3cd20052e55df9ecf185f3e6f7b9d4aa5992f0c6bc1259fc07

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 2140590fad0c6f31f12ec13fa3fa8b0c828a8f78ab526b5ec32f7c92756d7313
MD5 5763486d2979b6606120b88d72a5e81f
BLAKE2b-256 e07979c29d827b559fd51f7ab7f9160e5de7450cdc3eaacad873c02908e00730

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 28c9942f865c0e3f5a1d849b447877138ae40b42ac5e75bb1155454690410e60
MD5 11d4b734e9dd403bca4137b0ff95f8fd
BLAKE2b-256 fee46715d37c0644ea1296a5cb571497a29327a4e1bbce825238d9ef67eeffc0

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 050c268077c9086c7fdf8250efd33e1d57e26b38c4c291149329fe72a3c417b2
MD5 104b9f6abf0578e4b1dae9655a0dac60
BLAKE2b-256 447eb9256ba76e92eadc35252c8105c6fc4379be33384b3a3777796ef99bb458

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9248a801acb4d43f9e502b4955608cd9e0104ef3401daadeb2e6317cfa192829
MD5 7e2a2ba48e591bcb74f5c20fb8e8f3a1
BLAKE2b-256 2a7d8c96ac484e2853d52ec907e9f3eec18053810a50b523af1148a58e9ca5ad

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 2816f5d57134314c40c25664b23b1489a846731f6d9ff0df58bec575adcd02cc
MD5 f3ff69e6c557282916e4372ee6d78f8c
BLAKE2b-256 77a0f0d4f8199fc57250cb00378461039d988f8ddef39098f0647cdfa5c8dc31

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0e99de640657fd0bd6ad13c981023589bd85ee3b0192476dd2183112bd379c9f
MD5 4831f58fc4e12c04c3d08abc71564c75
BLAKE2b-256 3af4277502831bec614cbb3eab6c2057f188cb73161cd0a08fb1d7acca8d9197

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 70322917d5dfae726e213b73c15367ff4a76693e54bed44a24f05bc374f4b448
MD5 b732122aa48f7cf28e5c3d6aac0ff696
BLAKE2b-256 2c4bdc480e41bd924429220bfc20801b05c98b1a29698ad5b43ad8e579f0a7d0

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 18a99466c04124fc87723db6152bfbab8ea3633004256b621152f03573729635
MD5 a9b551024baf741286af419866a5c310
BLAKE2b-256 c530dc4f89301ffcf221ad426fcc1834d7e17624a08e93241211d098391df73f

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 a7ab4378c2c1eb47eefcbce2575379fb1e459eaf0de3cb1fabf67c0df89736b5
MD5 b02d1ed4ce7f21a6a7fe961c6b04df6d
BLAKE2b-256 907eaf4a93689b70bbbb47636e19161eab14d957fef0cee712c00f84d341184a

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 52f07d306964ff5d546da6dc199dd0fa3e90503e65faaeaf1bf2a41f83de3c09
MD5 f3a874b2b22c72bc1ed9a98b9be45f5f
BLAKE2b-256 7b79bb61081a2f17e45a297462bc0606460d5c528e24b970251f0ec510f9232f

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 0e6fe13582f9dedfd5981f6f8235cf49f6fdd64019497d6ce1aafab01f7e631d
MD5 1cedcd0e79b714c1b927e73a976d3b08
BLAKE2b-256 03d0f5f903df3e8b0e0425e2253f8cb941fe5431b155b54c5052c462ec1987b2

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-pp38-pypy38_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-pp38-pypy38_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 906943ae35846ed8c50121f887ecd51a0744eb36e6041047725011f13c435fe5
MD5 582b955231e42f0acb75d7fa2eeaece2
BLAKE2b-256 3c3d3b546ee1a5d4964ef4d99dac3a210a9d82cd51ddbe147c8d97e3351103bd

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8398e92881a592c586863b1c9c1d4ab663eeb8ebd7366e0bd26b68e93448267c
MD5 f43f74d407ae4f070142d14b6d158c49
BLAKE2b-256 2706c42870293dba8c3bcf40bea4d9d7a81e60b59b77ed3d837f4d84481cfa5d

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 c75c85c73ba9d6999508848e42757c20611fff38a130c65c164a0933b0823547
MD5 a14f6da205c6f302c0431d1beaaa9a76
BLAKE2b-256 ce8c0d2712708a37dd50509aa397cce071117db3aca948a9dbe01a5e0b55c1fb

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 f034dc37e8d8c36ce2424780da5ba7379d4c566bf74752d571214297813d2e3c
MD5 b84bbc7604b7142805c62bf6b18e23c1
BLAKE2b-256 8d465b392a771d8c08498434374815e122116ef58a2a83fcc6916fe64b328054

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 d737898a6076ea57aa3965a11df60d6c3a941120e5b079b4b15ef5af30f5b941
MD5 a98670fb0e778e3540d7b9ddd69dc8bd
BLAKE2b-256 62749fe9e96071956d320e3308816d9981fc98b391cad980f9535e222cd8ef9e

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2b1b0ec193bffc32e6c61ae39ccc69a937ec94e45bec1f640c10c0df3d4ab63a
MD5 726110961fd829bf82eafbf78576b7df
BLAKE2b-256 0b3a4979f4d8f684dcc6c275fcdd7eb63818c545a2ec76ae98b513f12247ae9b

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 45853a1649835abedae22c63c2b9101ef52c1e0db24363153236dea704871544
MD5 e52c36a15bbe9c7bf22e356c2e8d287a
BLAKE2b-256 7b78783eb610f00cb6cfc9ba189015368a701b5747a0bee021290c554704a77e

See more details on using hashes here.

File details

Details for the file y_py_dart-0.6.3a20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for y_py_dart-0.6.3a20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 891db4205f8b725c16d7ebc7160fea2677af54cd78d5eaf5d793796be202a414
MD5 a1ad8ac1f0c4e17d39e58677a05284c1
BLAKE2b-256 9bb40017ecef97778999254ba8bed7c11eec888daffc9dbb1697a58a60ad9a11

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