logust 0.3.2__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {logust-0.3.2 → logust-0.4.0}/.github/workflows/CI.yml +1 -1
- logust-0.4.0/.github/workflows/docs.yml +85 -0
- {logust-0.3.2 → logust-0.4.0}/.github/workflows/freethreaded-release.yml +1 -1
- {logust-0.3.2 → logust-0.4.0}/.github/workflows/test.yml +29 -3
- {logust-0.3.2 → logust-0.4.0}/CHANGELOG.md +10 -1
- {logust-0.3.2 → logust-0.4.0}/Cargo.lock +41 -43
- {logust-0.3.2 → logust-0.4.0}/Cargo.toml +2 -2
- {logust-0.3.2 → logust-0.4.0}/PKG-INFO +49 -1
- {logust-0.3.2 → logust-0.4.0}/README.md +48 -0
- {logust-0.3.2 → logust-0.4.0}/docs/api.md +89 -0
- {logust-0.3.2 → logust-0.4.0}/docs/getting-started/installation.md +10 -0
- logust-0.4.0/docs/guide/canonical-events.md +191 -0
- {logust-0.3.2 → logust-0.4.0}/docs/guide/formatting.md +15 -0
- {logust-0.3.2 → logust-0.4.0}/docs/guide/integrations.md +93 -3
- {logust-0.3.2 → logust-0.4.0}/docs/index.md +3 -0
- logust-0.4.0/examples/08_fastapi_integration.py +167 -0
- logust-0.4.0/examples/README.md +38 -0
- {logust-0.3.2 → logust-0.4.0}/logust/__init__.py +6 -2
- {logust-0.3.2 → logust-0.4.0}/logust/_logger.py +18 -11
- {logust-0.3.2 → logust-0.4.0}/logust/_logust.pyi +8 -0
- {logust-0.3.2 → logust-0.4.0}/logust/contrib/__init__.py +15 -0
- {logust-0.3.2 → logust-0.4.0}/logust/contrib/decorators.py +3 -3
- logust-0.4.0/logust/contrib/events.py +137 -0
- logust-0.4.0/logust/contrib/starlette.py +770 -0
- {logust-0.3.2 → logust-0.4.0}/mkdocs.yml +4 -0
- {logust-0.3.2 → logust-0.4.0}/src/format.rs +10 -10
- logust-0.4.0/src/handler.rs +762 -0
- {logust-0.3.2 → logust-0.4.0}/src/lib.rs +119 -34
- logust-0.4.0/tests/test_canonical_events.py +280 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_kwargs_extra.py +2 -2
- {logust-0.3.2 → logust-0.4.0}/tests/test_multiprocessing.py +2 -0
- logust-0.4.0/tests/test_starlette_middleware.py +386 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_starlette_security.py +4 -4
- logust-0.4.0/tests/test_typed_json_extra.py +670 -0
- logust-0.4.0/tests/test_web_integration.py +153 -0
- logust-0.3.2/.github/workflows/docs.yml +0 -44
- logust-0.3.2/examples/08_fastapi_integration.py +0 -179
- logust-0.3.2/logust/contrib/starlette.py +0 -381
- logust-0.3.2/src/handler.rs +0 -404
- logust-0.3.2/tests/test_starlette_middleware.py +0 -128
- {logust-0.3.2 → logust-0.4.0}/.github/CODEOWNERS +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/FUNDING.yml +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/release-drafter.yml +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/workflows/release-drafter.yml +0 -0
- {logust-0.3.2 → logust-0.4.0}/.github/workflows/security.yml +0 -0
- {logust-0.3.2 → logust-0.4.0}/.gitignore +0 -0
- {logust-0.3.2 → logust-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/CONTRIBUTING.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/LICENSE +0 -0
- {logust-0.3.2 → logust-0.4.0}/SECURITY.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/README.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/__init__.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/bench_filter_mixed.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/bench_format_record.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/bench_lazy_is_level.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/bench_throughput.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/benchmarks/conftest.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/assets/favicon.svg +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/assets/logo.svg +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/comparison.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/getting-started/quick-start.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/guide/context.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/guide/exceptions.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/guide/file-output.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/guide/levels.md +0 -0
- {logust-0.3.2 → logust-0.4.0}/docs/stylesheets/extra.css +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/01_basic_logging.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/02_file_output.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/03_json_serialization.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/04_context_binding.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/05_exception_handling.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/06_custom_levels.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/examples/07_callbacks.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/_opt.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/_parse.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/_template.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/_traceback.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/_types.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/contrib/logging_handler.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/logust/py.typed +0 -0
- {logust-0.3.2 → logust-0.4.0}/prek.toml +0 -0
- {logust-0.3.2 → logust-0.4.0}/pyproject.toml +0 -0
- {logust-0.3.2 → logust-0.4.0}/renovate.json +0 -0
- {logust-0.3.2 → logust-0.4.0}/src/level.rs +0 -0
- {logust-0.3.2 → logust-0.4.0}/src/sink.rs +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/__init__.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/conftest.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_callable_sink.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_callable_template.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_callbacks.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_caller_info.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_collect_options.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_configure.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_context.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_filter_fast_path.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_format_optimization.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_format_tokens.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_handlers.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_levels.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_logger.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_opt.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_parsing.py +0 -0
- {logust-0.3.2 → logust-0.4.0}/tests/test_token_registry.py +0 -0
|
@@ -172,7 +172,7 @@ jobs:
|
|
|
172
172
|
subject-path: 'wheels-*/*'
|
|
173
173
|
- name: Install uv
|
|
174
174
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
175
|
-
uses: astral-sh/setup-uv@v8.
|
|
175
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
176
176
|
- name: Publish to PyPI
|
|
177
177
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
178
178
|
run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/ 'wheels-*/*'
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: Deploy Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
version:
|
|
9
|
+
description: 'Version label (e.g. 0.3.2). Leave empty to deploy "dev".'
|
|
10
|
+
required: false
|
|
11
|
+
default: ''
|
|
12
|
+
set_latest:
|
|
13
|
+
description: 'Update the "latest" alias to this version.'
|
|
14
|
+
type: boolean
|
|
15
|
+
default: false
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
deploy:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Configure Git
|
|
29
|
+
run: |
|
|
30
|
+
git config user.name github-actions[bot]
|
|
31
|
+
git config user.email github-actions[bot]@users.noreply.github.com
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
uses: actions/setup-python@v6
|
|
35
|
+
with:
|
|
36
|
+
python-version: '3.14'
|
|
37
|
+
|
|
38
|
+
- name: Cache pip
|
|
39
|
+
uses: actions/cache@v5
|
|
40
|
+
with:
|
|
41
|
+
path: ~/.cache/pip
|
|
42
|
+
key: ${{ runner.os }}-pip-mkdocs-material-mike
|
|
43
|
+
restore-keys: |
|
|
44
|
+
${{ runner.os }}-pip-
|
|
45
|
+
|
|
46
|
+
- name: Install dependencies
|
|
47
|
+
run: pip install mkdocs-material mkdocstrings[python] mkdocs-minify-plugin mike
|
|
48
|
+
|
|
49
|
+
- name: Resolve version
|
|
50
|
+
id: version
|
|
51
|
+
env:
|
|
52
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
53
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
54
|
+
INPUT_VERSION: ${{ inputs.version }}
|
|
55
|
+
INPUT_SET_LATEST: ${{ inputs.set_latest }}
|
|
56
|
+
run: |
|
|
57
|
+
if [ "$EVENT_NAME" = "release" ]; then
|
|
58
|
+
tag="$RELEASE_TAG"
|
|
59
|
+
version="${tag#v}"
|
|
60
|
+
printf 'version=%s\n' "$version" >> "$GITHUB_OUTPUT"
|
|
61
|
+
printf 'alias=latest\n' >> "$GITHUB_OUTPUT"
|
|
62
|
+
else
|
|
63
|
+
version="$INPUT_VERSION"
|
|
64
|
+
if [ -z "$version" ]; then
|
|
65
|
+
version="dev"
|
|
66
|
+
fi
|
|
67
|
+
printf 'version=%s\n' "$version" >> "$GITHUB_OUTPUT"
|
|
68
|
+
if [ "$INPUT_SET_LATEST" = "true" ]; then
|
|
69
|
+
printf 'alias=latest\n' >> "$GITHUB_OUTPUT"
|
|
70
|
+
else
|
|
71
|
+
printf 'alias=\n' >> "$GITHUB_OUTPUT"
|
|
72
|
+
fi
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
- name: Deploy with mike
|
|
76
|
+
env:
|
|
77
|
+
MIKE_VERSION: ${{ steps.version.outputs.version }}
|
|
78
|
+
MIKE_ALIAS: ${{ steps.version.outputs.alias }}
|
|
79
|
+
run: |
|
|
80
|
+
if [ -n "$MIKE_ALIAS" ]; then
|
|
81
|
+
mike deploy --push --update-aliases "$MIKE_VERSION" "$MIKE_ALIAS"
|
|
82
|
+
mike set-default --push "$MIKE_ALIAS"
|
|
83
|
+
else
|
|
84
|
+
mike deploy --push "$MIKE_VERSION"
|
|
85
|
+
fi
|
|
@@ -84,7 +84,7 @@ jobs:
|
|
|
84
84
|
subject-path: 'wheels-*/*'
|
|
85
85
|
- name: Install uv
|
|
86
86
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
87
|
-
uses: astral-sh/setup-uv@v8.
|
|
87
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
88
88
|
- name: Publish to PyPI
|
|
89
89
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
90
90
|
run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/ 'wheels-*/*'
|
|
@@ -70,7 +70,7 @@ jobs:
|
|
|
70
70
|
uses: dtolnay/rust-toolchain@stable
|
|
71
71
|
|
|
72
72
|
- name: Install uv
|
|
73
|
-
uses: astral-sh/setup-uv@v8.
|
|
73
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
74
74
|
|
|
75
75
|
- name: Install dependencies and build
|
|
76
76
|
run: |
|
|
@@ -83,11 +83,37 @@ jobs:
|
|
|
83
83
|
|
|
84
84
|
- name: Upload coverage
|
|
85
85
|
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
|
|
86
|
-
uses: codecov/codecov-action@
|
|
86
|
+
uses: codecov/codecov-action@v7
|
|
87
87
|
with:
|
|
88
88
|
files: ./coverage.xml
|
|
89
89
|
fail_ci_if_error: false
|
|
90
90
|
|
|
91
|
+
web-integration-test:
|
|
92
|
+
name: Web Integration Tests
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/checkout@v6
|
|
96
|
+
|
|
97
|
+
- name: Set up Python
|
|
98
|
+
uses: actions/setup-python@v6
|
|
99
|
+
with:
|
|
100
|
+
python-version: '3.14'
|
|
101
|
+
|
|
102
|
+
- name: Install Rust
|
|
103
|
+
uses: dtolnay/rust-toolchain@stable
|
|
104
|
+
|
|
105
|
+
- name: Install uv
|
|
106
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
107
|
+
|
|
108
|
+
- name: Install dependencies and build
|
|
109
|
+
run: |
|
|
110
|
+
uv venv
|
|
111
|
+
uv pip install maturin pytest httpx fastapi starlette uuid-utils
|
|
112
|
+
uv run maturin develop
|
|
113
|
+
|
|
114
|
+
- name: Run web integration tests
|
|
115
|
+
run: uv run pytest tests/test_web_integration.py -v
|
|
116
|
+
|
|
91
117
|
lint:
|
|
92
118
|
name: Python Lint
|
|
93
119
|
runs-on: ubuntu-latest
|
|
@@ -103,7 +129,7 @@ jobs:
|
|
|
103
129
|
uses: dtolnay/rust-toolchain@stable
|
|
104
130
|
|
|
105
131
|
- name: Install uv
|
|
106
|
-
uses: astral-sh/setup-uv@v8.
|
|
132
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
107
133
|
|
|
108
134
|
- name: Install dependencies and build
|
|
109
135
|
run: |
|
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-06-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Canonical request events for web integrations**: `logust.contrib` now provides `canonical_event()`, `add_event_fields()`, `clear_event_fields()`, `get_event_fields()`, `get_current_event()`, and `TailSampler`, and Starlette/FastAPI middleware can emit one `http.request` event per request with request/response fields, endpoint-enriched extras, and tail sampling for errors and slow requests. (#38)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **JSON extra values handle more Python types**: `serialize=True` now emits `bytes` / `bytearray` extras as UTF-8 strings with replacement for invalid bytes, `set` / `frozenset` extras as arrays, `datetime` / `date` / `time` extras as `.isoformat()` strings, and `Enum` extras via their `.value` converted with the same rules. Text formatting (`{extra[key]}`) and Python callback records still use the existing `str(value)` view. Other object types such as `Decimal`, `UUID`, `Path`, and `complex` continue to fall back to `str(value)` in JSON.
|
|
17
|
+
|
|
10
18
|
## [0.3.2] - 2026-05-07
|
|
11
19
|
|
|
12
20
|
### Added
|
|
@@ -131,7 +139,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
131
139
|
- 1.3x faster than Python standard logging
|
|
132
140
|
- Lock-free fast path for filtered messages
|
|
133
141
|
|
|
134
|
-
[Unreleased]: https://github.com/yamaaaaaa31/logust/compare/v0.
|
|
142
|
+
[Unreleased]: https://github.com/yamaaaaaa31/logust/compare/v0.4.0...HEAD
|
|
143
|
+
[0.4.0]: https://github.com/yamaaaaaa31/logust/compare/v0.3.2...v0.4.0
|
|
135
144
|
[0.3.2]: https://github.com/yamaaaaaa31/logust/compare/v0.3.1...v0.3.2
|
|
136
145
|
[0.3.1]: https://github.com/yamaaaaaa31/logust/compare/v0.3.0...v0.3.1
|
|
137
146
|
[0.3.0]: https://github.com/yamaaaaaa31/logust/compare/v0.2.1...v0.3.0
|
|
@@ -19,27 +19,27 @@ dependencies = [
|
|
|
19
19
|
|
|
20
20
|
[[package]]
|
|
21
21
|
name = "autocfg"
|
|
22
|
-
version = "1.5.
|
|
22
|
+
version = "1.5.1"
|
|
23
23
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
24
|
-
checksum = "
|
|
24
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
25
25
|
|
|
26
26
|
[[package]]
|
|
27
27
|
name = "bitflags"
|
|
28
|
-
version = "2.
|
|
28
|
+
version = "2.13.0"
|
|
29
29
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
30
|
-
checksum = "
|
|
30
|
+
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|
31
31
|
|
|
32
32
|
[[package]]
|
|
33
33
|
name = "bumpalo"
|
|
34
|
-
version = "3.20.
|
|
34
|
+
version = "3.20.3"
|
|
35
35
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
-
checksum = "
|
|
36
|
+
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
37
37
|
|
|
38
38
|
[[package]]
|
|
39
39
|
name = "cc"
|
|
40
|
-
version = "1.2.
|
|
40
|
+
version = "1.2.64"
|
|
41
41
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
|
-
checksum = "
|
|
42
|
+
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
|
|
43
43
|
dependencies = [
|
|
44
44
|
"find-msvc-tools",
|
|
45
45
|
"shlex",
|
|
@@ -53,9 +53,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
|
53
53
|
|
|
54
54
|
[[package]]
|
|
55
55
|
name = "chrono"
|
|
56
|
-
version = "0.4.
|
|
56
|
+
version = "0.4.45"
|
|
57
57
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
58
|
-
checksum = "
|
|
58
|
+
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
|
59
59
|
dependencies = [
|
|
60
60
|
"iana-time-zone",
|
|
61
61
|
"js-sys",
|
|
@@ -182,13 +182,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
|
182
182
|
|
|
183
183
|
[[package]]
|
|
184
184
|
name = "js-sys"
|
|
185
|
-
version = "0.3.
|
|
185
|
+
version = "0.3.102"
|
|
186
186
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
187
|
-
checksum = "
|
|
187
|
+
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
|
|
188
188
|
dependencies = [
|
|
189
189
|
"cfg-if",
|
|
190
190
|
"futures-util",
|
|
191
|
-
"once_cell",
|
|
192
191
|
"wasm-bindgen",
|
|
193
192
|
]
|
|
194
193
|
|
|
@@ -209,13 +208,13 @@ dependencies = [
|
|
|
209
208
|
|
|
210
209
|
[[package]]
|
|
211
210
|
name = "log"
|
|
212
|
-
version = "0.4.
|
|
211
|
+
version = "0.4.32"
|
|
213
212
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
214
|
-
checksum = "
|
|
213
|
+
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
|
215
214
|
|
|
216
215
|
[[package]]
|
|
217
216
|
name = "logust"
|
|
218
|
-
version = "0.
|
|
217
|
+
version = "0.4.0"
|
|
219
218
|
dependencies = [
|
|
220
219
|
"chrono",
|
|
221
220
|
"colored",
|
|
@@ -231,9 +230,9 @@ dependencies = [
|
|
|
231
230
|
|
|
232
231
|
[[package]]
|
|
233
232
|
name = "memchr"
|
|
234
|
-
version = "2.8.
|
|
233
|
+
version = "2.8.2"
|
|
235
234
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
236
|
-
checksum = "
|
|
235
|
+
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
|
237
236
|
|
|
238
237
|
[[package]]
|
|
239
238
|
name = "miniz_oxide"
|
|
@@ -306,9 +305,9 @@ dependencies = [
|
|
|
306
305
|
|
|
307
306
|
[[package]]
|
|
308
307
|
name = "pyo3"
|
|
309
|
-
version = "0.
|
|
308
|
+
version = "0.29.0"
|
|
310
309
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
311
|
-
checksum = "
|
|
310
|
+
checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c"
|
|
312
311
|
dependencies = [
|
|
313
312
|
"libc",
|
|
314
313
|
"once_cell",
|
|
@@ -320,18 +319,18 @@ dependencies = [
|
|
|
320
319
|
|
|
321
320
|
[[package]]
|
|
322
321
|
name = "pyo3-build-config"
|
|
323
|
-
version = "0.
|
|
322
|
+
version = "0.29.0"
|
|
324
323
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
325
|
-
checksum = "
|
|
324
|
+
checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078"
|
|
326
325
|
dependencies = [
|
|
327
326
|
"target-lexicon",
|
|
328
327
|
]
|
|
329
328
|
|
|
330
329
|
[[package]]
|
|
331
330
|
name = "pyo3-ffi"
|
|
332
|
-
version = "0.
|
|
331
|
+
version = "0.29.0"
|
|
333
332
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
334
|
-
checksum = "
|
|
333
|
+
checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b"
|
|
335
334
|
dependencies = [
|
|
336
335
|
"libc",
|
|
337
336
|
"pyo3-build-config",
|
|
@@ -339,9 +338,9 @@ dependencies = [
|
|
|
339
338
|
|
|
340
339
|
[[package]]
|
|
341
340
|
name = "pyo3-macros"
|
|
342
|
-
version = "0.
|
|
341
|
+
version = "0.29.0"
|
|
343
342
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
344
|
-
checksum = "
|
|
343
|
+
checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771"
|
|
345
344
|
dependencies = [
|
|
346
345
|
"proc-macro2",
|
|
347
346
|
"pyo3-macros-backend",
|
|
@@ -351,13 +350,12 @@ dependencies = [
|
|
|
351
350
|
|
|
352
351
|
[[package]]
|
|
353
352
|
name = "pyo3-macros-backend"
|
|
354
|
-
version = "0.
|
|
353
|
+
version = "0.29.0"
|
|
355
354
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
356
|
-
checksum = "
|
|
355
|
+
checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362"
|
|
357
356
|
dependencies = [
|
|
358
357
|
"heck",
|
|
359
358
|
"proc-macro2",
|
|
360
|
-
"pyo3-build-config",
|
|
361
359
|
"quote",
|
|
362
360
|
"syn",
|
|
363
361
|
]
|
|
@@ -424,9 +422,9 @@ dependencies = [
|
|
|
424
422
|
|
|
425
423
|
[[package]]
|
|
426
424
|
name = "serde_json"
|
|
427
|
-
version = "1.0.
|
|
425
|
+
version = "1.0.150"
|
|
428
426
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
429
|
-
checksum = "
|
|
427
|
+
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
|
430
428
|
dependencies = [
|
|
431
429
|
"itoa",
|
|
432
430
|
"memchr",
|
|
@@ -437,9 +435,9 @@ dependencies = [
|
|
|
437
435
|
|
|
438
436
|
[[package]]
|
|
439
437
|
name = "shlex"
|
|
440
|
-
version = "
|
|
438
|
+
version = "2.0.1"
|
|
441
439
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
442
|
-
checksum = "
|
|
440
|
+
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|
443
441
|
|
|
444
442
|
[[package]]
|
|
445
443
|
name = "simd-adler32"
|
|
@@ -455,9 +453,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
|
|
455
453
|
|
|
456
454
|
[[package]]
|
|
457
455
|
name = "smallvec"
|
|
458
|
-
version = "1.15.
|
|
456
|
+
version = "1.15.2"
|
|
459
457
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
460
|
-
checksum = "
|
|
458
|
+
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
|
461
459
|
|
|
462
460
|
[[package]]
|
|
463
461
|
name = "syn"
|
|
@@ -484,9 +482,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
|
484
482
|
|
|
485
483
|
[[package]]
|
|
486
484
|
name = "wasm-bindgen"
|
|
487
|
-
version = "0.2.
|
|
485
|
+
version = "0.2.125"
|
|
488
486
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
489
|
-
checksum = "
|
|
487
|
+
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
|
|
490
488
|
dependencies = [
|
|
491
489
|
"cfg-if",
|
|
492
490
|
"once_cell",
|
|
@@ -497,9 +495,9 @@ dependencies = [
|
|
|
497
495
|
|
|
498
496
|
[[package]]
|
|
499
497
|
name = "wasm-bindgen-macro"
|
|
500
|
-
version = "0.2.
|
|
498
|
+
version = "0.2.125"
|
|
501
499
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
502
|
-
checksum = "
|
|
500
|
+
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
|
|
503
501
|
dependencies = [
|
|
504
502
|
"quote",
|
|
505
503
|
"wasm-bindgen-macro-support",
|
|
@@ -507,9 +505,9 @@ dependencies = [
|
|
|
507
505
|
|
|
508
506
|
[[package]]
|
|
509
507
|
name = "wasm-bindgen-macro-support"
|
|
510
|
-
version = "0.2.
|
|
508
|
+
version = "0.2.125"
|
|
511
509
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
512
|
-
checksum = "
|
|
510
|
+
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
|
|
513
511
|
dependencies = [
|
|
514
512
|
"bumpalo",
|
|
515
513
|
"proc-macro2",
|
|
@@ -520,9 +518,9 @@ dependencies = [
|
|
|
520
518
|
|
|
521
519
|
[[package]]
|
|
522
520
|
name = "wasm-bindgen-shared"
|
|
523
|
-
version = "0.2.
|
|
521
|
+
version = "0.2.125"
|
|
524
522
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
525
|
-
checksum = "
|
|
523
|
+
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
|
|
526
524
|
dependencies = [
|
|
527
525
|
"unicode-ident",
|
|
528
526
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "logust"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ name = "_logust"
|
|
|
9
9
|
crate-type = ["cdylib"]
|
|
10
10
|
|
|
11
11
|
[dependencies]
|
|
12
|
-
pyo3 = { version = "0.
|
|
12
|
+
pyo3 = { version = "0.29.0", features = ["extension-module"] }
|
|
13
13
|
chrono = { version = "0.4", features = ["serde"] }
|
|
14
14
|
colored = "3.0"
|
|
15
15
|
flate2 = "1.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: logust
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -68,6 +68,7 @@ A fast, Rust-powered Python logging library inspired by [loguru](https://github.
|
|
|
68
68
|
- **Custom Levels** - Define your own log levels with colors and icons
|
|
69
69
|
- **Color Markup** - Inline `<red>color</red>` tags in log messages
|
|
70
70
|
- **Async Writing** - Optional thread-safe async file writes with `enqueue=True`
|
|
71
|
+
- **Canonical Events** - Request-scoped wide events with built-in tail sampling
|
|
71
72
|
- **Free-Threaded Python** - Release automation builds wheels for CPython 3.13t and 3.14t on Linux and macOS
|
|
72
73
|
- **Zero-Config Integrations** - Built-in support for standard logging, FastAPI, and function timing
|
|
73
74
|
|
|
@@ -503,6 +504,14 @@ async def fetch_user(user_id):
|
|
|
503
504
|
|
|
504
505
|
### FastAPI / Starlette Middleware
|
|
505
506
|
|
|
507
|
+
Install the matching extra for web middleware:
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
pip install "logust[fastapi]"
|
|
511
|
+
# or
|
|
512
|
+
pip install "logust[starlette]"
|
|
513
|
+
```
|
|
514
|
+
|
|
506
515
|
```python
|
|
507
516
|
from fastapi import FastAPI
|
|
508
517
|
from logust.contrib.starlette import setup_fastapi
|
|
@@ -516,6 +525,45 @@ setup_fastapi(app, skip_routes=["/health"])
|
|
|
516
525
|
# - Standard logging redirected to logust
|
|
517
526
|
```
|
|
518
527
|
|
|
528
|
+
### Canonical Request Events
|
|
529
|
+
|
|
530
|
+
Emit one wide event at request completion, then keep high-value events with tail sampling:
|
|
531
|
+
|
|
532
|
+
```python
|
|
533
|
+
from fastapi import FastAPI
|
|
534
|
+
from logust.contrib import add_event_fields
|
|
535
|
+
from logust.contrib.starlette import setup_fastapi
|
|
536
|
+
|
|
537
|
+
app = FastAPI()
|
|
538
|
+
|
|
539
|
+
setup_fastapi(
|
|
540
|
+
app,
|
|
541
|
+
canonical=True,
|
|
542
|
+
sample_rate=0.02,
|
|
543
|
+
slow_ms=1000,
|
|
544
|
+
skip_routes=["/health"],
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
@app.post("/checkout")
|
|
548
|
+
async def checkout(user_id: str):
|
|
549
|
+
add_event_fields({"user.id": user_id}, feature_checkout_v2=True)
|
|
550
|
+
return {"ok": True}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
The middleware logs a single `http.request` event with request, response, timing,
|
|
554
|
+
trace context, and any fields added during the request. Errors and slow requests
|
|
555
|
+
are kept even when normal successful traffic is sampled. JSON sinks preserve
|
|
556
|
+
numeric, boolean, list, dict, and null extra values as native JSON types. Incoming
|
|
557
|
+
`x-request-id` values are preserved; otherwise Logust generates a short
|
|
558
|
+
`uuid4`-based request ID.
|
|
559
|
+
`sample_rate` must be between `0.0` and `1.0`, and `slow_ms` must be non-negative.
|
|
560
|
+
|
|
561
|
+
See [docs/guide/canonical-events.md](docs/guide/canonical-events.md) and
|
|
562
|
+
[examples/08_fastapi_integration.py](examples/08_fastapi_integration.py) for the
|
|
563
|
+
full contract and a runnable FastAPI app.
|
|
564
|
+
|
|
565
|
+
More runnable examples are listed in [examples/README.md](examples/README.md).
|
|
566
|
+
|
|
519
567
|
## Complete API Reference
|
|
520
568
|
|
|
521
569
|
### Logger Methods
|
|
@@ -22,6 +22,7 @@ A fast, Rust-powered Python logging library inspired by [loguru](https://github.
|
|
|
22
22
|
- **Custom Levels** - Define your own log levels with colors and icons
|
|
23
23
|
- **Color Markup** - Inline `<red>color</red>` tags in log messages
|
|
24
24
|
- **Async Writing** - Optional thread-safe async file writes with `enqueue=True`
|
|
25
|
+
- **Canonical Events** - Request-scoped wide events with built-in tail sampling
|
|
25
26
|
- **Free-Threaded Python** - Release automation builds wheels for CPython 3.13t and 3.14t on Linux and macOS
|
|
26
27
|
- **Zero-Config Integrations** - Built-in support for standard logging, FastAPI, and function timing
|
|
27
28
|
|
|
@@ -457,6 +458,14 @@ async def fetch_user(user_id):
|
|
|
457
458
|
|
|
458
459
|
### FastAPI / Starlette Middleware
|
|
459
460
|
|
|
461
|
+
Install the matching extra for web middleware:
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
pip install "logust[fastapi]"
|
|
465
|
+
# or
|
|
466
|
+
pip install "logust[starlette]"
|
|
467
|
+
```
|
|
468
|
+
|
|
460
469
|
```python
|
|
461
470
|
from fastapi import FastAPI
|
|
462
471
|
from logust.contrib.starlette import setup_fastapi
|
|
@@ -470,6 +479,45 @@ setup_fastapi(app, skip_routes=["/health"])
|
|
|
470
479
|
# - Standard logging redirected to logust
|
|
471
480
|
```
|
|
472
481
|
|
|
482
|
+
### Canonical Request Events
|
|
483
|
+
|
|
484
|
+
Emit one wide event at request completion, then keep high-value events with tail sampling:
|
|
485
|
+
|
|
486
|
+
```python
|
|
487
|
+
from fastapi import FastAPI
|
|
488
|
+
from logust.contrib import add_event_fields
|
|
489
|
+
from logust.contrib.starlette import setup_fastapi
|
|
490
|
+
|
|
491
|
+
app = FastAPI()
|
|
492
|
+
|
|
493
|
+
setup_fastapi(
|
|
494
|
+
app,
|
|
495
|
+
canonical=True,
|
|
496
|
+
sample_rate=0.02,
|
|
497
|
+
slow_ms=1000,
|
|
498
|
+
skip_routes=["/health"],
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
@app.post("/checkout")
|
|
502
|
+
async def checkout(user_id: str):
|
|
503
|
+
add_event_fields({"user.id": user_id}, feature_checkout_v2=True)
|
|
504
|
+
return {"ok": True}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
The middleware logs a single `http.request` event with request, response, timing,
|
|
508
|
+
trace context, and any fields added during the request. Errors and slow requests
|
|
509
|
+
are kept even when normal successful traffic is sampled. JSON sinks preserve
|
|
510
|
+
numeric, boolean, list, dict, and null extra values as native JSON types. Incoming
|
|
511
|
+
`x-request-id` values are preserved; otherwise Logust generates a short
|
|
512
|
+
`uuid4`-based request ID.
|
|
513
|
+
`sample_rate` must be between `0.0` and `1.0`, and `slow_ms` must be non-negative.
|
|
514
|
+
|
|
515
|
+
See [docs/guide/canonical-events.md](docs/guide/canonical-events.md) and
|
|
516
|
+
[examples/08_fastapi_integration.py](examples/08_fastapi_integration.py) for the
|
|
517
|
+
full contract and a runnable FastAPI app.
|
|
518
|
+
|
|
519
|
+
More runnable examples are listed in [examples/README.md](examples/README.md).
|
|
520
|
+
|
|
473
521
|
## Complete API Reference
|
|
474
522
|
|
|
475
523
|
### Logger Methods
|
|
@@ -7,6 +7,8 @@ Quick reference for the public API. For examples, see the Guide.
|
|
|
7
7
|
- **Logger**: Log methods, handlers, levels, context, options, callbacks
|
|
8
8
|
- **LogLevel**: Enum values for severity
|
|
9
9
|
- **Parsing**: `parse()` and `parse_json()` helpers
|
|
10
|
+
- **Contrib**: standard logging interception, decorators, canonical events,
|
|
11
|
+
FastAPI/Starlette middleware
|
|
10
12
|
|
|
11
13
|
## Logger
|
|
12
14
|
|
|
@@ -176,6 +178,93 @@ LogLevel.Critical # 50
|
|
|
176
178
|
|
|
177
179
|
---
|
|
178
180
|
|
|
181
|
+
## Contrib
|
|
182
|
+
|
|
183
|
+
Utilities in `logust.contrib` are optional helpers built on top of the core
|
|
184
|
+
logger.
|
|
185
|
+
|
|
186
|
+
### Standard logging interception
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from logust.contrib import InterceptHandler, intercept_logging
|
|
190
|
+
|
|
191
|
+
intercept_logging()
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Function timing
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
from logust.contrib import debug_fn, log_fn
|
|
198
|
+
|
|
199
|
+
@log_fn
|
|
200
|
+
def work():
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
@debug_fn
|
|
204
|
+
async def async_work():
|
|
205
|
+
pass
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Canonical event helpers
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from logust.contrib import (
|
|
212
|
+
TailSampler,
|
|
213
|
+
add_event_fields,
|
|
214
|
+
canonical_event,
|
|
215
|
+
clear_event_fields,
|
|
216
|
+
get_current_event,
|
|
217
|
+
get_event_fields,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
with canonical_event({"event": "job"}) as event:
|
|
221
|
+
add_event_fields(job_id="job_123")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`add_event_fields(fields=None, **kwargs)` returns `True` when an event is active
|
|
225
|
+
and `False` outside a canonical event context.
|
|
226
|
+
|
|
227
|
+
`TailSampler` accepts:
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
TailSampler(
|
|
231
|
+
rate=1.0, # 0.0 to 1.0
|
|
232
|
+
always_keep_errors=True,
|
|
233
|
+
slow_ms=None, # non-negative milliseconds
|
|
234
|
+
keep_if=None, # predicate(event) -> bool
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### FastAPI / Starlette
|
|
239
|
+
|
|
240
|
+
Install web extras before importing the middleware:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pip install "logust[fastapi]"
|
|
244
|
+
# or
|
|
245
|
+
pip install "logust[starlette]"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from logust.contrib.starlette import (
|
|
250
|
+
RequestLoggerMiddleware,
|
|
251
|
+
get_request_id,
|
|
252
|
+
setup_fastapi,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
setup_fastapi(
|
|
256
|
+
app,
|
|
257
|
+
canonical=True,
|
|
258
|
+
sample_rate=0.05,
|
|
259
|
+
slow_ms=1000,
|
|
260
|
+
skip_routes=["/health"],
|
|
261
|
+
)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
For the full event contract, see [Canonical Events](guide/canonical-events.md).
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
179
268
|
## Type definitions
|
|
180
269
|
|
|
181
270
|
### LogRecord
|