Skip to main content

The settingspec cover

SettingSpec Check Crates.io Version PyPI Version NPM Version

SettingSpec

  1. Concepts
    1. Single file convenience
    2. Declarative profiles as environments
    3. Language independent
    4. Easy secrets
      1. SecretSpec
      2. Dotenv
      3. Cottage or agebox
  2. Learn more

Concepts

Single file convenience

With a single source of truth, i.e., settingspec.toml, you don't need to mentally merge settings from multiple files, say common.toml, dev.toml, prod.toml, etc. No surprise overwrites. One file for all environments, all languages, all submodules.

Declarative profiles as environments

[spec]                               # Optional: Declare the specification here
profile.key = "SETTINGSPEC_PROFILE"  # Default: Environment variable name to switch between profiles
profile.options = [                  # Optional: Enables strict checking of per-profile declarations
  "dev",
  "stage",
  "prod",
]
profile.default = "dev"  # Optional: Default profile when the switch is not set

[settings]                 # Declare the settings here with syntax: `<key>.<profile>.<directive> = <value>`
key1.default.val = "val1"  # Default value for all profiles
key1.prod.val = "prod1"    # Override the default value when SETTINGSPEC_PROFILE=prod

# Strictly define different values for different profiles
key2.dev.val = "dev2"      # When SETTINGSPEC_PROFILE=dev, key2=dev2
key2.stage.val = "stage2"
key2.prod.val = "prod2"

Overrides are intentional and kept in plain sight (see key1).

By not defining a default value, you can ensure that you never miss adding a value for a specific profile (e.g. this file will refuse to load if key2.prod declaration is missing).

Language independent

The command-line tool settingspec can export the final settings into well-known formats such as toml, json, yaml, etc., or hard-coded modules such as .py, .js, .lua, etc., write them to disk, print, or pipe them via stdin or even export as environment variables, allowing you to use a single settingspec.toml without worrying about the target language.

[spec]
export.file = true  # Default: Export all settings into settings.toml
# export.file = {   # Optional: Fine-grained control over what to export
#   "settings.json" = true,
#   "settings.yaml" = {
#     key1 = true,
#     group1 = true,
#     group2.subgroup = true,
#     group3.subgroup.key1 = false,
#     "#tag1" = true,
#   },
# }
export.skip_gitignore = false  # Default: Auto-append exported files to .gitignore if inside a git repo
export.mode = 0x600     # Default: File permission mode for the exported files
export.keep = false     # Default: Cleanup the exported files after the program exits
export.stdout = "toml"  # Optional: Print in toml format
export.env = "PREFIX_"  # Optional: Export as environment variables prefixed with this string
export.stdin = "toml"   # Optional: Pass settings to program stdin in specified format

[settings]
key1.default.val = "val1"
group1.key1.default.val = "group1val1"
group2.subgroup.key1.default.val = "group2val1"
group3.subgroup.key1.default.val = "group3val1"
group3.subgroup.key1.default.tags = ["tag1", "tag2"]

Now export the final settings as declared.

settingspec export

Or keep watching to export when settingspec.toml changes.

settingspec watch

Or directly run the program with exported settings.

settingspec run -- [your program]...

If no export option is specified, the default behavior is to export all settings into settings.toml.

Easy secrets

Unlike regular settings, secrets aren't supposed to be easily visible. So, they are best declared inside hidden/encrypted files and passed via environment variables or via stdin.

However, with SettingSpec, we can ensure that they are actually set and also include them in the final exported settings.

SecretSpec

You can pair up SettingSpec with a declarative secrets manager such as SecretSpec.

secretspec.toml

[project]
name = "my-app"
revision = "1.0"

[profiles.default]
SECRET1 = { description = "Secret One", required = true }
SECRET2 = { description = "Secret Two", required = false }

settingspec.toml

[spec]
profile.options = ["dev", "stage", "prod"]

[settings]
secret1.default.env = "SECRET1"  # Load value from $SECRET1

# Override the default value from environment variables
secret2.default.val = "defaultvalue"  # Default value if $SECRET2 is not set
secret2.default.env = "SECRET2"       # Load value from $SECRET2 if set
secret2.prod.env = "PRODSECRET"       # Load value from $PRODSECRET if SETTINGSPEC_PROFILE=prod

With these set up, run:

secretspec run -- settingspec run -- [your program]...

Dotenv

Or keep things simple with Dotenv.

[spec]
profile.options = ["dev", "stage", "prod"]

envfile.default = ".env"    # Default environment file
envfile.stage = ".env.age"  # Also supports age-encrypted env files
envfile.prod = "-"          # Read from stdin, encrypted or not

# decryption.key.env = "SETTINGSPEC_DECRYPTION_KEY"  # Default
# decryption.key.path = "~/.ssh/"                    # Default

[settings]
secret1.default.env = "SECRET1"     # Load value from $SECRET1

Cottage or agebox

Too simple? Use Cottage or agebox.

[spec]
envfile.default = ".env.cott.age"
# envfile.default = ".env.agebox"

decryption.key.path = "~/.config/cottage/identity:~/.ssh"
decryption.key.env = "COTTAGE_IDENTITY"
# decryption.key.env = "AGEBOX_PRIVATE_KEYS"

[settings]
secret.default.env = "SECRET"

Learn more

Check out the settingspec.toml example file and full specification for more details.

Metadata

Release files for settingspec 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for settingspec 0.6.0
File Size Uploaded
settingspec-0.6.0.tar.gz 44.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for settingspec 0.6.0
File
settingspec-0.6.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
settingspec-0.6.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
settingspec-0.6.0-py3-none-win32.whl Python 3 none Windows x86-32 Details
settingspec-0.6.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
settingspec-0.6.0-py3-none-musllinux_1_2_i686.whl Python 3 none Linux musl 1.2+ x86-32 Details
settingspec-0.6.0-py3-none-musllinux_1_2_armv7l.whl Python 3 none Linux musl 1.2+ ARMv7l Details
settingspec-0.6.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
settingspec-0.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
settingspec-0.6.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl Python 3 none Linux glibc 2.17+ IBM System/390x Details
settingspec-0.6.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl Python 3 none Linux glibc 2.17+ PowerPC 64-le Details
settingspec-0.6.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl Python 3 none Linux glibc 2.17+ x86-32 Details
settingspec-0.6.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl Python 3 none Linux glibc 2.17+ ARMv7l Details
settingspec-0.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
settingspec-0.6.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
settingspec-0.6.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 14.9 MB

Release files / settingspec-0.6.0.tar.gz

Download URL settingspec-0.6.0.tar.gz
Size 44.3 kB
Tags Source
SHA-256 checksum
How to use checksums
e2b7810972cd65239e7a9cb89663ffce0496bda12d986081984055b08ad4f2fd
BLAKE2b-256 checksum
How to use checksums
280ed26411ce879ce778ccb52087d14564984f519d538918cf4cc6512bcb9418
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-win_arm64.whl

Download URL settingspec-0.6.0-py3-none-win_arm64.whl
Size 851.2 kB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
0bbf440744cf52eda655f3e334a9e1846a3e38bffa19962fcaeadd031d048110
BLAKE2b-256 checksum
How to use checksums
b6d9c90c57decb5be2b077a9e040e7f45472406a4b345a9cde77ca3d777bc44c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-win_amd64.whl

Download URL settingspec-0.6.0-py3-none-win_amd64.whl
Size 916.1 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
4c526fb3769f1908734c8b51023e6c3452c8a8b60a52792cf11d0d6df15ff700
BLAKE2b-256 checksum
How to use checksums
8288b9cd4d690ab28a171cfb39fca1e9f1d5eca5a9a6c526fd8579972660c766
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-win32.whl

Download URL settingspec-0.6.0-py3-none-win32.whl
Size 888.6 kB
Tags Python 3 Windows x86-32
SHA-256 checksum
How to use checksums
ee91ad9286f9e030d4c5c4654d145a977ff2bb6c30d16d877d2adc12e929b974
BLAKE2b-256 checksum
How to use checksums
c4934ba6070f98159b963a10dfa957a87dac45d6ed1d353d2cbcaef121efdbf9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-musllinux_1_2_x86_64.whl

Download URL settingspec-0.6.0-py3-none-musllinux_1_2_x86_64.whl
Size 1.1 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
d2d89a7d2d0aa5d474554251433c10093a97374739dcbd8b941c4653d66f7450
BLAKE2b-256 checksum
How to use checksums
4f44929a0921b3a6d4543745d8c41b80479f7d334bae69d2edd7e113e34f3112
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-musllinux_1_2_i686.whl

Download URL settingspec-0.6.0-py3-none-musllinux_1_2_i686.whl
Size 1.1 MB
Tags Linux musl 1.2+ x86-32 Python 3
SHA-256 checksum
How to use checksums
98091535580ef85a7f476219412bb6b68d2a8e62429df5d64b23d8c6cdc71b93
BLAKE2b-256 checksum
How to use checksums
e82cd28bb6d349dda598b4da0a6819f1a62fae64bd9c92679883744c95de13fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-musllinux_1_2_armv7l.whl

Download URL settingspec-0.6.0-py3-none-musllinux_1_2_armv7l.whl
Size 1.0 MB
Tags Linux musl 1.2+ ARMv7l Python 3
SHA-256 checksum
How to use checksums
f46a66e94d4eb0d671e78e5508d7c30f1ecfc335b6ed5e3af57ca7fd92ae22c9
BLAKE2b-256 checksum
How to use checksums
7efaa83f4ef1009b8584deaa7fe98f1776265c507dabd7e4092f6ac955d45038
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-musllinux_1_2_aarch64.whl

Download URL settingspec-0.6.0-py3-none-musllinux_1_2_aarch64.whl
Size 987.5 kB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
0f7421a76b4ab714e5d04ff325c16089d704854bdf398bc823f83f4919a9b8a6
BLAKE2b-256 checksum
How to use checksums
f249be38243d5ecd4228928b12171ad1e0116948c3fa53fdb46f3365cd201f72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL settingspec-0.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.0 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
b2b461b56444a4ed3ee671c5d79c59195b274e96ca8ea43699687197f93185c1
BLAKE2b-256 checksum
How to use checksums
b3c92a215210217f20ba3ab0feca6d22626324a58c4c107022ad005d4ae86771
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl

Download URL settingspec-0.6.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Size 1.1 MB
Tags Linux glibc 2.17+ IBM System/390x Python 3
SHA-256 checksum
How to use checksums
88544d69ca7bb9d2cfe058b888f58a9c0fe5c9117ec1f40b9dc85c24d8692f4e
BLAKE2b-256 checksum
How to use checksums
332c49171ac520785c356feed05dbc73f5ee5e8f45e2669b528346656633f68a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl

Download URL settingspec-0.6.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Size 1.1 MB
Tags Linux glibc 2.17+ PowerPC 64-le Python 3
SHA-256 checksum
How to use checksums
60867a9e4fd71318b49060f6c2f632cd4e5fbd2bc3fb99b2765a2561f084065e
BLAKE2b-256 checksum
How to use checksums
449c9bf2731d86e8e9de897a60affbbb991284151e3bc1b702c23df72bbe452e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl

Download URL settingspec-0.6.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Size 1.1 MB
Tags Linux glibc 2.17+ x86-32 Python 3
SHA-256 checksum
How to use checksums
f2f083b9749b911ad35dcbba80afdbb23a828fbc5a4725f3f0d6373475847a7c
BLAKE2b-256 checksum
How to use checksums
727ab80d101ca98d9faf674fe2d2ecfb65c1370cce751629345d1283669d9313
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl

Download URL settingspec-0.6.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Size 989.2 kB
Tags Linux glibc 2.17+ ARMv7l Python 3
SHA-256 checksum
How to use checksums
19ca8bfdb107aa5df44608ad7bc91db2b4ec091cf61e0c1436c0ac9bd8ac9aab
BLAKE2b-256 checksum
How to use checksums
d50972aa24accd01b2ce36c793bfa2316301fd3831c640d4adbe5a9031d3df78
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL settingspec-0.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 941.2 kB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
054c3d02907b2597de28bf3df65e8c241b271e6931e80cf7f6f389fab0fcacea
BLAKE2b-256 checksum
How to use checksums
b8581b630131ca9a3a0f674292c1cc1f282b85437689a9a7ba20234d90af5252
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-macosx_11_0_arm64.whl

Download URL settingspec-0.6.0-py3-none-macosx_11_0_arm64.whl
Size 884.6 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
477fdf3e23ca211dbca389e3865f0b4dd4d45442b6ab7e1a06e479a7c6ef80d4
BLAKE2b-256 checksum
How to use checksums
824f9ae42364176d769b61c16be988b0cbda160132c8f6966af70b87a2498b11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / settingspec-0.6.0-py3-none-macosx_10_12_x86_64.whl

Download URL settingspec-0.6.0-py3-none-macosx_10_12_x86_64.whl
Size 975.3 kB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
40ad8675efe1dd5306ff9eea49c736f70d0d8a4beeef227324c2d743ae9b75f2
BLAKE2b-256 checksum
How to use checksums
c1cf2d0ed0f29e3da2169ff0e2c2e1d8e3a0b26a6692c15b63d4346b94ed87ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.7.0

16 release files

This release

0.6.0 This release

16 release files

0.5.1

16 release files

0.5.0

16 release files

0.4.0

16 release files

0.3.0

16 release files

0.2.0

16 release files

0.1.2

16 release files

0.1.1

16 release files

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page