Last-stop signals for automation failures.
Project description
Shuuten sends structured Slack and email alerts when your Python automations fail — especially in AWS Lambda and ECS — with minimal setup and zero dependencies.
終点 (Shūten) means "final stop" in Japanese — the point where a workflow ends and signals that something needs attention.
📖 Documentation · ⭐ Star on GitHub
Quick start (AWS Lambda)
import shuuten
@shuuten.capture
def lambda_handler(event, context):
shuuten.debug('debug info') # not sent
shuuten.error('domain error') # sent to Slack
1 / 0 # sent with stack trace
Set one environment variable and you’re done (see Slack webhook setup):
export SHUUTEN_SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
Why Shuuten?
- Built for failure paths — only
ERROR+signals are sent by default - Zero dependencies — no SDKs, agents, or background workers
- Designed for AWS — Lambda, ECS tasks, and containers work out of the box
- Logging-native — uses familiar
loggingsemantics - Opinionated but minimal — small surface area, easy to reason about
Installation
pip install shuuten # no dependencies (Slack, local logging)
pip install "shuuten[email]" # SES email (boto3) outside AWS Lambda
Usage patterns
Structured logging (logging-style)
import shuuten
def handler(event, context):
shuuten.info('hello') # not sent
shuuten.error('bad input') # sent to Slack if configured
Explicit logger + email notifications
Requires SES env vars (
SHUUTEN_SES_FROM,SHUUTEN_SES_TO). Email is sent via AWS SES if configured.
import shuuten
shuuten.init(shuuten.Config(app='my-app', env='dev'))
log = shuuten.get_logger(__name__)
@shuuten.capture(workflow='my-workflow')
def handler(event, context):
log.critical('Something went wrong') # sent to Slack + Email (if configured)
Manual context control (advanced)
import shuuten
def handler(event, context):
token = shuuten.detect_and_set_context(context)
try:
...
finally:
shuuten.reset_runtime_context(token)
The
capture()decorator works for ECS tasks as well (via ECS metadata v4).
Structured logging with extra
Works with both
shuuten.info()andlog = shuuten.get_logger(__name__)— any logger usingShuutenJSONFormatter.
Attach structured context with data
Pass a dict under the data key in extra to merge fields top-level into the
JSON log output:
shuuten.info('Incoming event', extra={
'data': {
'method': 'POST',
'path': '/slack/events',
'status': 200,
}
})
# → {"ts": ..., "level": "info", "msg": "Incoming event", "method": "POST", "path": "/slack/events", "status": 200, ...}
Note: Keys in
datamust not conflict with shuuten's built-in output fields (ts,fn,file,lineno,level,msg,logger,stack,kind,shuuten,exc). AValueErroris raised if they do:ValueError: shuuten: extra 'data' keys ['msg'] conflict with built-in log output fields.
Attach internal shuuten context
Use the shuuten key to attach structured metadata that is nested under a
shuuten field in the output:
shuuten.info('Processing request', extra={'shuuten': {'caller': 'my_fn', 'request_id': '123'}})
# → {"ts": ..., "msg": "Processing request", "shuuten": {"caller": "my_fn", "request_id": "123"}, ...}
Log a dict or list directly as msg
Pass a Python dict or list directly as the message — it will be embedded
as a native JSON object rather than a stringified representation:
shuuten.info({'event': 'app_requested', 'app_id': 'A123', 'scopes': ['incoming-webhook']})
# → {"ts": ..., "msg": {"event": "app_requested", "app_id": "A123", "scopes": [...]}, ...}
This also works with shuuten.get_logger():
log = shuuten.get_logger(__name__)
log.info({'event': 'app_requested', 'app_id': 'A123'})
Configuration
You can configure Shuuten via Config in code or environment variables.
| Variable | Description | Default |
|---|---|---|
SHUUTEN_APP |
Application name (used for grouping/metadata) | auto |
SHUUTEN_ENV |
Environment name (prod, dev, staging, etc.) |
auto |
SHUUTEN_MIN_LEVEL |
Minimum level sent to destinations | ERROR |
SHUUTEN_EMIT_LOCAL_LOG |
Emit local structured log when notifying | true |
SHUUTEN_QUIET_LEVEL |
Silence noisy third-party logs (e.g. boto) | WARNING |
SHUUTEN_DEDUPE_WINDOW_S |
Slack dedupe window (seconds); 0 disables |
30 |
Slack
| Variable | Description |
|---|---|
SHUUTEN_SLACK_WEBHOOK_URL |
Slack Incoming Webhook URL |
SHUUTEN_SLACK_FORMAT |
blocks or plain |
Email (SES)
| Variable | Description |
|---|---|
SHUUTEN_SES_FROM |
Verified SES sender |
SHUUTEN_SES_TO |
Comma-separated recipient list |
SHUUTEN_SES_REPLY_TO |
Optional reply-to address |
SHUUTEN_SES_REGION |
Optional SES region |
Supported destinations
- Slack (Incoming Webhooks)
- Email (AWS SES)
Note: When running in AWS (e.g. Lambda or ECS), the execution role must be allowed to send email via SES. See AWS docs.
Roadmap
- PagerDuty and other alerting destinations
- Context manager for exception capture
- Optional "exceptions-only" alerting mode
- Expanded ECS and EKS support
Credits
Created with Cookiecutter using https://github.com/audreyfeldroy/cookiecutter-pypackage
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shuuten-0.3.0.tar.gz.
File metadata
- Download URL: shuuten-0.3.0.tar.gz
- Upload date:
- Size: 29.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae676f2d1b9607ac07272931272ad06ff837048e44956e36a2b74cfa89aa7ec5
|
|
| MD5 |
6185ee5d5af77eb23501ac6d48130ca0
|
|
| BLAKE2b-256 |
1c7e9b284b578dd9e42a52e2aea93de68981b502c73085fc4ccbcd8906b90e83
|
Provenance
The following attestation bundles were made for shuuten-0.3.0.tar.gz:
Publisher:
release.yml on rnag/shuuten
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shuuten-0.3.0.tar.gz -
Subject digest:
ae676f2d1b9607ac07272931272ad06ff837048e44956e36a2b74cfa89aa7ec5 - Sigstore transparency entry: 1866394591
- Sigstore integration time:
-
Permalink:
rnag/shuuten@978206f8f3800b5b7042810ce11e2c3ae404135f -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/rnag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@978206f8f3800b5b7042810ce11e2c3ae404135f -
Trigger Event:
push
-
Statement type:
File details
Details for the file shuuten-0.3.0-py3-none-any.whl.
File metadata
- Download URL: shuuten-0.3.0-py3-none-any.whl
- Upload date:
- Size: 26.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
003139ca749fa90407ef6b36d8ea921da7eb9743c77b0cf6eb241a0b49b96e00
|
|
| MD5 |
363a6b509f6b4ee184fed8b63c830560
|
|
| BLAKE2b-256 |
a9bc8fd100ed8d8c3865ac8f6df87cf481c65952f93dfaa73ed5cb8d44763788
|
Provenance
The following attestation bundles were made for shuuten-0.3.0-py3-none-any.whl:
Publisher:
release.yml on rnag/shuuten
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shuuten-0.3.0-py3-none-any.whl -
Subject digest:
003139ca749fa90407ef6b36d8ea921da7eb9743c77b0cf6eb241a0b49b96e00 - Sigstore transparency entry: 1866394602
- Sigstore integration time:
-
Permalink:
rnag/shuuten@978206f8f3800b5b7042810ce11e2c3ae404135f -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/rnag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@978206f8f3800b5b7042810ce11e2c3ae404135f -
Trigger Event:
push
-
Statement type: