instruktai-python-logger 0.6.7__tar.gz → 0.7.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.
Files changed (24) hide show
  1. instruktai_python_logger-0.7.0/LICENSE +21 -0
  2. instruktai_python_logger-0.7.0/PKG-INFO +194 -0
  3. instruktai_python_logger-0.7.0/README.md +185 -0
  4. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/instrukt_ai_logging/logging.py +10 -262
  5. instruktai_python_logger-0.7.0/instruktai_python_logger.egg-info/PKG-INFO +194 -0
  6. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/instruktai_python_logger.egg-info/SOURCES.txt +2 -6
  7. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/pyproject.toml +2 -6
  8. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/tests/test_configure_logging.py +7 -2
  9. instruktai_python_logger-0.7.0/tests/test_resolve_log_files.py +64 -0
  10. instruktai_python_logger-0.6.7/PKG-INFO +0 -129
  11. instruktai_python_logger-0.6.7/README.md +0 -122
  12. instruktai_python_logger-0.6.7/instrukt_ai_logging/cli.py +0 -271
  13. instruktai_python_logger-0.6.7/instrukt_ai_logging/install.py +0 -245
  14. instruktai_python_logger-0.6.7/instruktai_python_logger.egg-info/PKG-INFO +0 -129
  15. instruktai_python_logger-0.6.7/instruktai_python_logger.egg-info/entry_points.txt +0 -3
  16. instruktai_python_logger-0.6.7/tests/test_cli_follow.py +0 -46
  17. instruktai_python_logger-0.6.7/tests/test_install.py +0 -301
  18. instruktai_python_logger-0.6.7/tests/test_log_aggregation.py +0 -292
  19. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/instrukt_ai_logging/__init__.py +0 -0
  20. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/instrukt_ai_logging/py.typed +0 -0
  21. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/instruktai_python_logger.egg-info/dependency_links.txt +0 -0
  22. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/instruktai_python_logger.egg-info/top_level.txt +0 -0
  23. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/setup.cfg +0 -0
  24. {instruktai_python_logger-0.6.7 → instruktai_python_logger-0.7.0}/tests/test_trace_logging.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 InstruktAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.4
2
+ Name: instruktai-python-logger
3
+ Version: 0.7.0
4
+ Summary: InstruktAI logging contract for Python services: one-call stdlib logging setup writing the shared logfmt files.
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Dynamic: license-file
9
+
10
+ # InstruktAI logging
11
+
12
+ One logging contract for InstruktAI services, in three parts:
13
+
14
+ - **`instrukt-ai-logs`** and **`instrukt-ai-log-setup`**: the Rust tool that
15
+ reads and merges an app's logs and wires per-user log rotation.
16
+ - **`instrukt-ai-logging`**: a Rust writer crate (a `tracing` layer).
17
+ - **`instruktai-python-logger`**: the Python writer SDK (module
18
+ `instrukt_ai_logging`, stdlib `logging`).
19
+
20
+ Both writers follow the same contract, [`docs/contract.md`](docs/contract.md):
21
+ the same four env vars, the same single-line logfmt format, the same file
22
+ location. A Rust service and a Python service of one app write identical lines
23
+ into the same directory, and the tool reads both. The executable form of the
24
+ contract is the shared fixture tree under [`conformance/`](conformance/).
25
+
26
+ The contract keeps logs useful from a tail window, for people and for AIs that
27
+ only read the last lines: third-party noise is held back, every event is one
28
+ human-readable line, secrets are redacted and very long values truncated.
29
+ Background in [`docs/design.md`](docs/design.md); release process in
30
+ [`docs/publishing.md`](docs/publishing.md).
31
+
32
+ ## Install the tool
33
+
34
+ ```bash
35
+ curl -LsSf https://github.com/InstruktAI/logging/releases/latest/download/instrukt-ai-logs-installer.sh | sh
36
+ ```
37
+
38
+ This installs both binaries, `instrukt-ai-logs` and `instrukt-ai-log-setup`,
39
+ into `$XDG_BIN_HOME` or `~/.local/bin` (macOS on Apple silicon and Intel, Linux
40
+ x86_64 and aarch64). Rust users can build it instead:
41
+
42
+ ```bash
43
+ cargo install instrukt-ai-logs
44
+ ```
45
+
46
+ Up to 0.6.x the two commands came with the Python package. If you installed
47
+ them that way (`uv tool install instruktai-python-logger`, `pipx`, or `pip`),
48
+ remove that install first so the old scripts do not shadow the new binaries,
49
+ for example `uv tool uninstall instruktai-python-logger`. See
50
+ [`CHANGELOG.md`](CHANGELOG.md).
51
+
52
+ ## Read logs
53
+
54
+ ```bash
55
+ # Last 10 minutes (the default)
56
+ instrukt-ai-logs teleclaude
57
+
58
+ # Last 2 hours
59
+ instrukt-ai-logs teleclaude --since 2h
60
+
61
+ # Keep matching lines, then drop matching lines (Python-style regex)
62
+ instrukt-ai-logs teleclaude --since 10m --grep 'logger=teleclaude' --exclude 'level=DEBUG'
63
+
64
+ # Print the window, then follow new lines (tail -f style); Ctrl-C to stop
65
+ instrukt-ai-logs teleclaude --since 10m --follow
66
+
67
+ # Only some per-process files
68
+ instrukt-ai-logs teleclaude --since 1h --logs=cron,docs-watch
69
+ ```
70
+
71
+ `--since` takes `<n>s`, `<n>m`, `<n>h` or `<n>d`. Without `--logs`, every
72
+ `*.log*` file in the app's directory is merged by timestamp, rotated and
73
+ gzip-compressed archives included. `--logs` (alias `--include`) selects exact
74
+ stems: `--logs=cron` reads `cron.log`, `cron.log.0`, `cron.log.1.gz` and never
75
+ `cron-backup.log`. Follow mode follows each stem's live `<stem>.log`, waits
76
+ for one that does not exist yet, and keeps following across rotation and
77
+ truncation. When nothing matches, a note on stderr names the directory read
78
+ and its newest entry.
79
+
80
+ ## Write logs from Python
81
+
82
+ ```bash
83
+ pip install instruktai-python-logger
84
+ ```
85
+
86
+ ```py
87
+ import logging
88
+ from instrukt_ai_logging import configure_logging
89
+
90
+ configure_logging("teleclaude")
91
+ logger = logging.getLogger("teleclaude.core")
92
+ logger.info("job_started", job_id="abc123", user_id=123)
93
+ ```
94
+
95
+ ```text
96
+ 2026-11-05T09:30:12.345Z level=INFO logger=teleclaude.core msg="job_started" job_id=abc123 user_id=123
97
+ ```
98
+
99
+ `configure_logging` returns the log file path. `get_logger(name)` returns a
100
+ logger typed for named `**kv` fields; `TRACE` is a level below `DEBUG`.
101
+ `resolve_log_file(app, source=...)` and `resolve_log_files(app, stems=...)`
102
+ locate files without configuring anything.
103
+
104
+ ## Write logs from Rust
105
+
106
+ ```bash
107
+ cargo add instrukt-ai-logging tracing
108
+ ```
109
+
110
+ ```rust
111
+ fn main() -> Result<(), instrukt_ai_logging::Error> {
112
+ // $XDG_STATE_HOME/instrukt-ai/teleclaude/teleclaude.log
113
+ let path = instrukt_ai_logging::init("teleclaude", None)?;
114
+ tracing::info!(job_id = "abc123", attempt = 3, "job_started");
115
+ println!("logging to {}", path.display());
116
+ Ok(())
117
+ }
118
+ ```
119
+
120
+ `init` installs the global subscriber and bridges the `log` crate. The
121
+ `Builder` sets a `source`, `max_message_chars`, extra app prefixes
122
+ (`app_prefix("my_app_core")`), or returns a `Layer` for a subscriber you
123
+ compose yourself. Details in
124
+ [`crates/instrukt-ai-logging/README.md`](crates/instrukt-ai-logging/README.md).
125
+
126
+ ## Per-process log files
127
+
128
+ Several processes of one app (a daemon, a watcher, a cron job) can each write
129
+ their own file in the app's directory by passing a source:
130
+
131
+ ```py
132
+ configure_logging("teleclaude") # teleclaude.log
133
+ configure_logging("teleclaude", source="docs-watch") # docs-watch.log
134
+ ```
135
+
136
+ ```rust
137
+ instrukt_ai_logging::init("teleclaude", Some("cron"))?; // cron.log
138
+ ```
139
+
140
+ Pass the bare stem; `.log` is always appended. `instrukt-ai-logs` merges them.
141
+
142
+ ## Environment variables
143
+
144
+ Per app, with the app name upper-cased as prefix (here `TELECLAUDE_`):
145
+
146
+ | Variable | Meaning | Default |
147
+ | --- | --- | --- |
148
+ | `TELECLAUDE_LOG_LEVEL` | threshold for the app's own loggers | `INFO` |
149
+ | `TELECLAUDE_THIRD_PARTY_LOG_LEVEL` | threshold for third-party loggers | `WARNING` |
150
+ | `TELECLAUDE_THIRD_PARTY_LOGGERS` | comma-separated third-party prefixes to spotlight at the third-party level, e.g. `httpcore,telegram`; every other third-party logger then passes at `WARNING`+ | none |
151
+ | `TELECLAUDE_MUTED_LOGGERS` | comma-separated prefixes held at `WARNING`+, e.g. `teleclaude.cli.tui` | none |
152
+
153
+ These four are the whole configuration surface. The longest matching prefix
154
+ decides; the exact rules are in [`docs/contract.md`](docs/contract.md).
155
+
156
+ ## Log location
157
+
158
+ ```text
159
+ $XDG_STATE_HOME/instrukt-ai/{app}/{source or app}.log
160
+ ```
161
+
162
+ with `~/.local/state` when `XDG_STATE_HOME` is unset, on macOS and Linux
163
+ alike. There is no override. The location is user-writable, and both writers
164
+ fail at startup when the file cannot be opened: a process that cannot write
165
+ its logs does not start blind.
166
+
167
+ ## Rotation
168
+
169
+ Rotation runs entirely as the user. Run once per machine:
170
+
171
+ ```bash
172
+ instrukt-ai-log-setup
173
+ ```
174
+
175
+ It writes a rotation config under `~/.config/instrukt-ai/` and a per-user
176
+ scheduler: a launchd LaunchAgent running `newsyslog` on macOS, a systemd user
177
+ timer running `logrotate` on Linux. Each log rotates at 50 MB and 30 gzipped
178
+ archives are kept. Re-running on a wired machine reports healthy; problems are
179
+ printed and the exit code is 1. The writers never touch rotation; they reopen
180
+ their file when it has been rotated away. No `/etc` configuration and no sudo.
181
+
182
+ ## Development
183
+
184
+ `make install` prepares the Python and Rust toolchains; `make install-runtime`
185
+ runs the setup from this checkout. Gates:
186
+
187
+ ```bash
188
+ uv run ruff check . && uv run ruff format --check . && uv run pyright && uv run mypy && uv run pytest
189
+ cargo fmt --all --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace
190
+ ```
191
+
192
+ ## License
193
+
194
+ MIT
@@ -0,0 +1,185 @@
1
+ # InstruktAI logging
2
+
3
+ One logging contract for InstruktAI services, in three parts:
4
+
5
+ - **`instrukt-ai-logs`** and **`instrukt-ai-log-setup`**: the Rust tool that
6
+ reads and merges an app's logs and wires per-user log rotation.
7
+ - **`instrukt-ai-logging`**: a Rust writer crate (a `tracing` layer).
8
+ - **`instruktai-python-logger`**: the Python writer SDK (module
9
+ `instrukt_ai_logging`, stdlib `logging`).
10
+
11
+ Both writers follow the same contract, [`docs/contract.md`](docs/contract.md):
12
+ the same four env vars, the same single-line logfmt format, the same file
13
+ location. A Rust service and a Python service of one app write identical lines
14
+ into the same directory, and the tool reads both. The executable form of the
15
+ contract is the shared fixture tree under [`conformance/`](conformance/).
16
+
17
+ The contract keeps logs useful from a tail window, for people and for AIs that
18
+ only read the last lines: third-party noise is held back, every event is one
19
+ human-readable line, secrets are redacted and very long values truncated.
20
+ Background in [`docs/design.md`](docs/design.md); release process in
21
+ [`docs/publishing.md`](docs/publishing.md).
22
+
23
+ ## Install the tool
24
+
25
+ ```bash
26
+ curl -LsSf https://github.com/InstruktAI/logging/releases/latest/download/instrukt-ai-logs-installer.sh | sh
27
+ ```
28
+
29
+ This installs both binaries, `instrukt-ai-logs` and `instrukt-ai-log-setup`,
30
+ into `$XDG_BIN_HOME` or `~/.local/bin` (macOS on Apple silicon and Intel, Linux
31
+ x86_64 and aarch64). Rust users can build it instead:
32
+
33
+ ```bash
34
+ cargo install instrukt-ai-logs
35
+ ```
36
+
37
+ Up to 0.6.x the two commands came with the Python package. If you installed
38
+ them that way (`uv tool install instruktai-python-logger`, `pipx`, or `pip`),
39
+ remove that install first so the old scripts do not shadow the new binaries,
40
+ for example `uv tool uninstall instruktai-python-logger`. See
41
+ [`CHANGELOG.md`](CHANGELOG.md).
42
+
43
+ ## Read logs
44
+
45
+ ```bash
46
+ # Last 10 minutes (the default)
47
+ instrukt-ai-logs teleclaude
48
+
49
+ # Last 2 hours
50
+ instrukt-ai-logs teleclaude --since 2h
51
+
52
+ # Keep matching lines, then drop matching lines (Python-style regex)
53
+ instrukt-ai-logs teleclaude --since 10m --grep 'logger=teleclaude' --exclude 'level=DEBUG'
54
+
55
+ # Print the window, then follow new lines (tail -f style); Ctrl-C to stop
56
+ instrukt-ai-logs teleclaude --since 10m --follow
57
+
58
+ # Only some per-process files
59
+ instrukt-ai-logs teleclaude --since 1h --logs=cron,docs-watch
60
+ ```
61
+
62
+ `--since` takes `<n>s`, `<n>m`, `<n>h` or `<n>d`. Without `--logs`, every
63
+ `*.log*` file in the app's directory is merged by timestamp, rotated and
64
+ gzip-compressed archives included. `--logs` (alias `--include`) selects exact
65
+ stems: `--logs=cron` reads `cron.log`, `cron.log.0`, `cron.log.1.gz` and never
66
+ `cron-backup.log`. Follow mode follows each stem's live `<stem>.log`, waits
67
+ for one that does not exist yet, and keeps following across rotation and
68
+ truncation. When nothing matches, a note on stderr names the directory read
69
+ and its newest entry.
70
+
71
+ ## Write logs from Python
72
+
73
+ ```bash
74
+ pip install instruktai-python-logger
75
+ ```
76
+
77
+ ```py
78
+ import logging
79
+ from instrukt_ai_logging import configure_logging
80
+
81
+ configure_logging("teleclaude")
82
+ logger = logging.getLogger("teleclaude.core")
83
+ logger.info("job_started", job_id="abc123", user_id=123)
84
+ ```
85
+
86
+ ```text
87
+ 2026-11-05T09:30:12.345Z level=INFO logger=teleclaude.core msg="job_started" job_id=abc123 user_id=123
88
+ ```
89
+
90
+ `configure_logging` returns the log file path. `get_logger(name)` returns a
91
+ logger typed for named `**kv` fields; `TRACE` is a level below `DEBUG`.
92
+ `resolve_log_file(app, source=...)` and `resolve_log_files(app, stems=...)`
93
+ locate files without configuring anything.
94
+
95
+ ## Write logs from Rust
96
+
97
+ ```bash
98
+ cargo add instrukt-ai-logging tracing
99
+ ```
100
+
101
+ ```rust
102
+ fn main() -> Result<(), instrukt_ai_logging::Error> {
103
+ // $XDG_STATE_HOME/instrukt-ai/teleclaude/teleclaude.log
104
+ let path = instrukt_ai_logging::init("teleclaude", None)?;
105
+ tracing::info!(job_id = "abc123", attempt = 3, "job_started");
106
+ println!("logging to {}", path.display());
107
+ Ok(())
108
+ }
109
+ ```
110
+
111
+ `init` installs the global subscriber and bridges the `log` crate. The
112
+ `Builder` sets a `source`, `max_message_chars`, extra app prefixes
113
+ (`app_prefix("my_app_core")`), or returns a `Layer` for a subscriber you
114
+ compose yourself. Details in
115
+ [`crates/instrukt-ai-logging/README.md`](crates/instrukt-ai-logging/README.md).
116
+
117
+ ## Per-process log files
118
+
119
+ Several processes of one app (a daemon, a watcher, a cron job) can each write
120
+ their own file in the app's directory by passing a source:
121
+
122
+ ```py
123
+ configure_logging("teleclaude") # teleclaude.log
124
+ configure_logging("teleclaude", source="docs-watch") # docs-watch.log
125
+ ```
126
+
127
+ ```rust
128
+ instrukt_ai_logging::init("teleclaude", Some("cron"))?; // cron.log
129
+ ```
130
+
131
+ Pass the bare stem; `.log` is always appended. `instrukt-ai-logs` merges them.
132
+
133
+ ## Environment variables
134
+
135
+ Per app, with the app name upper-cased as prefix (here `TELECLAUDE_`):
136
+
137
+ | Variable | Meaning | Default |
138
+ | --- | --- | --- |
139
+ | `TELECLAUDE_LOG_LEVEL` | threshold for the app's own loggers | `INFO` |
140
+ | `TELECLAUDE_THIRD_PARTY_LOG_LEVEL` | threshold for third-party loggers | `WARNING` |
141
+ | `TELECLAUDE_THIRD_PARTY_LOGGERS` | comma-separated third-party prefixes to spotlight at the third-party level, e.g. `httpcore,telegram`; every other third-party logger then passes at `WARNING`+ | none |
142
+ | `TELECLAUDE_MUTED_LOGGERS` | comma-separated prefixes held at `WARNING`+, e.g. `teleclaude.cli.tui` | none |
143
+
144
+ These four are the whole configuration surface. The longest matching prefix
145
+ decides; the exact rules are in [`docs/contract.md`](docs/contract.md).
146
+
147
+ ## Log location
148
+
149
+ ```text
150
+ $XDG_STATE_HOME/instrukt-ai/{app}/{source or app}.log
151
+ ```
152
+
153
+ with `~/.local/state` when `XDG_STATE_HOME` is unset, on macOS and Linux
154
+ alike. There is no override. The location is user-writable, and both writers
155
+ fail at startup when the file cannot be opened: a process that cannot write
156
+ its logs does not start blind.
157
+
158
+ ## Rotation
159
+
160
+ Rotation runs entirely as the user. Run once per machine:
161
+
162
+ ```bash
163
+ instrukt-ai-log-setup
164
+ ```
165
+
166
+ It writes a rotation config under `~/.config/instrukt-ai/` and a per-user
167
+ scheduler: a launchd LaunchAgent running `newsyslog` on macOS, a systemd user
168
+ timer running `logrotate` on Linux. Each log rotates at 50 MB and 30 gzipped
169
+ archives are kept. Re-running on a wired machine reports healthy; problems are
170
+ printed and the exit code is 1. The writers never touch rotation; they reopen
171
+ their file when it has been rotated away. No `/etc` configuration and no sudo.
172
+
173
+ ## Development
174
+
175
+ `make install` prepares the Python and Rust toolchains; `make install-runtime`
176
+ runs the setup from this checkout. Gates:
177
+
178
+ ```bash
179
+ uv run ruff check . && uv run ruff format --check . && uv run pyright && uv run mypy && uv run pytest
180
+ cargo fmt --all --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace
181
+ ```
182
+
183
+ ## License
184
+
185
+ MIT