instruktai-python-logger 0.6.2__tar.gz → 0.6.4__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.
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/PKG-INFO +15 -9
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/README.md +14 -8
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/install.py +12 -2
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/logging.py +0 -7
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instruktai_python_logger.egg-info/PKG-INFO +15 -9
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/pyproject.toml +1 -1
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_configure_logging.py +1 -30
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_install.py +52 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/__init__.py +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/cli.py +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/py.typed +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instruktai_python_logger.egg-info/SOURCES.txt +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instruktai_python_logger.egg-info/dependency_links.txt +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instruktai_python_logger.egg-info/entry_points.txt +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instruktai_python_logger.egg-info/top_level.txt +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/setup.cfg +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_cli_follow.py +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_log_aggregation.py +0 -0
- {instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_trace_logging.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: instruktai-python-logger
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4
|
|
4
4
|
Summary: Centralized logging utilities for Python services.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -28,6 +28,10 @@ From GitHub:
|
|
|
28
28
|
pip install git+ssh://git@github.com/InstruktAI/python-logger.git
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
For a local checkout, `make install` prepares dependencies and development
|
|
32
|
+
tooling only. Run `make install-runtime` separately when this user's rotation
|
|
33
|
+
scheduler should be wired.
|
|
34
|
+
|
|
31
35
|
## API
|
|
32
36
|
|
|
33
37
|
- Python entrypoint: `instrukt_ai_logging.configure_logging(...)`
|
|
@@ -88,14 +92,16 @@ write its logs must not start blind.
|
|
|
88
92
|
|
|
89
93
|
## Rotation
|
|
90
94
|
|
|
91
|
-
Rotation
|
|
92
|
-
`
|
|
93
|
-
per-user scheduler
|
|
94
|
-
systemd user timer on Linux running `logrotate
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
Rotation runs entirely in user space. At deploy, run
|
|
96
|
+
`instrukt-ai-log-setup` once (or `make install-runtime` in this repository) to
|
|
97
|
+
wire the per-user rotation conf plus scheduler: a launchd LaunchAgent on macOS
|
|
98
|
+
running `newsyslog`, or a systemd user timer on Linux running `logrotate`.
|
|
99
|
+
Re-running setup on an already-wired machine reports healthy.
|
|
100
|
+
|
|
101
|
+
`configure_logging(...)` only creates and opens the log file; it never writes
|
|
102
|
+
rotation assets or invokes launchd/systemd. No `/etc` configuration, no sudo,
|
|
103
|
+
and no system rotation daemon ever touches these files, so rotated/recreated
|
|
104
|
+
logs always stay owned by the producing user.
|
|
99
105
|
|
|
100
106
|
## CLI
|
|
101
107
|
|
|
@@ -21,6 +21,10 @@ From GitHub:
|
|
|
21
21
|
pip install git+ssh://git@github.com/InstruktAI/python-logger.git
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
For a local checkout, `make install` prepares dependencies and development
|
|
25
|
+
tooling only. Run `make install-runtime` separately when this user's rotation
|
|
26
|
+
scheduler should be wired.
|
|
27
|
+
|
|
24
28
|
## API
|
|
25
29
|
|
|
26
30
|
- Python entrypoint: `instrukt_ai_logging.configure_logging(...)`
|
|
@@ -81,14 +85,16 @@ write its logs must not start blind.
|
|
|
81
85
|
|
|
82
86
|
## Rotation
|
|
83
87
|
|
|
84
|
-
Rotation
|
|
85
|
-
`
|
|
86
|
-
per-user scheduler
|
|
87
|
-
systemd user timer on Linux running `logrotate
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
Rotation runs entirely in user space. At deploy, run
|
|
89
|
+
`instrukt-ai-log-setup` once (or `make install-runtime` in this repository) to
|
|
90
|
+
wire the per-user rotation conf plus scheduler: a launchd LaunchAgent on macOS
|
|
91
|
+
running `newsyslog`, or a systemd user timer on Linux running `logrotate`.
|
|
92
|
+
Re-running setup on an already-wired machine reports healthy.
|
|
93
|
+
|
|
94
|
+
`configure_logging(...)` only creates and opens the log file; it never writes
|
|
95
|
+
rotation assets or invokes launchd/systemd. No `/etc` configuration, no sudo,
|
|
96
|
+
and no system rotation daemon ever touches these files, so rotated/recreated
|
|
97
|
+
logs always stay owned by the producing user.
|
|
92
98
|
|
|
93
99
|
## CLI
|
|
94
100
|
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/install.py
RENAMED
|
@@ -155,9 +155,19 @@ def _ensure_launchd_loaded(plist_path: Path) -> list[str]:
|
|
|
155
155
|
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
156
156
|
return [f"launchctl bootstrap failed to run: {exc}"]
|
|
157
157
|
|
|
158
|
-
if result.returncode
|
|
158
|
+
if result.returncode == 0 or "already bootstrapped" in result.stderr.lower():
|
|
159
|
+
return []
|
|
160
|
+
|
|
161
|
+
# macOS reports EIO(5), not "already bootstrapped", when re-bootstrapping an already-loaded agent.
|
|
162
|
+
# Confirm with `print` exit status; a nonzero result preserves the original bootstrap failure.
|
|
163
|
+
try:
|
|
164
|
+
loaded_result = _run_scheduler_command(["launchctl", "print", f"gui/{uid}/{_LAUNCHD_LABEL}"])
|
|
165
|
+
except (OSError, subprocess.TimeoutExpired):
|
|
159
166
|
return [f"launchctl bootstrap failed: {result.stderr.strip()}"]
|
|
160
|
-
|
|
167
|
+
|
|
168
|
+
if loaded_result.returncode == 0:
|
|
169
|
+
return []
|
|
170
|
+
return [f"launchctl bootstrap failed: {result.stderr.strip()}"]
|
|
161
171
|
|
|
162
172
|
|
|
163
173
|
def _ensure_systemd_loaded() -> list[str]:
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/logging.py
RENAMED
|
@@ -12,8 +12,6 @@ from logging.handlers import WatchedFileHandler
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any, Protocol, cast, runtime_checkable
|
|
14
14
|
|
|
15
|
-
from instrukt_ai_logging.install import ensure_rotation
|
|
16
|
-
|
|
17
15
|
# Standard logging levels are: NOTSET=0, DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50
|
|
18
16
|
TRACE: int = 5
|
|
19
17
|
logging.addLevelName(TRACE, "TRACE")
|
|
@@ -485,11 +483,6 @@ def configure_logging(
|
|
|
485
483
|
for prefix in muted:
|
|
486
484
|
logging.getLogger(prefix).setLevel(logging.WARNING)
|
|
487
485
|
|
|
488
|
-
# Rotation bootstrap is not logging: a failure here is surfaced as a
|
|
489
|
-
# warning, never fatal to an already-working log file.
|
|
490
|
-
for problem in ensure_rotation():
|
|
491
|
-
logging.getLogger(app_logger_prefix).warning("log rotation ensure problem: %s", problem)
|
|
492
|
-
|
|
493
486
|
return log_file
|
|
494
487
|
|
|
495
488
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: instruktai-python-logger
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4
|
|
4
4
|
Summary: Centralized logging utilities for Python services.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -28,6 +28,10 @@ From GitHub:
|
|
|
28
28
|
pip install git+ssh://git@github.com/InstruktAI/python-logger.git
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
For a local checkout, `make install` prepares dependencies and development
|
|
32
|
+
tooling only. Run `make install-runtime` separately when this user's rotation
|
|
33
|
+
scheduler should be wired.
|
|
34
|
+
|
|
31
35
|
## API
|
|
32
36
|
|
|
33
37
|
- Python entrypoint: `instrukt_ai_logging.configure_logging(...)`
|
|
@@ -88,14 +92,16 @@ write its logs must not start blind.
|
|
|
88
92
|
|
|
89
93
|
## Rotation
|
|
90
94
|
|
|
91
|
-
Rotation
|
|
92
|
-
`
|
|
93
|
-
per-user scheduler
|
|
94
|
-
systemd user timer on Linux running `logrotate
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
Rotation runs entirely in user space. At deploy, run
|
|
96
|
+
`instrukt-ai-log-setup` once (or `make install-runtime` in this repository) to
|
|
97
|
+
wire the per-user rotation conf plus scheduler: a launchd LaunchAgent on macOS
|
|
98
|
+
running `newsyslog`, or a systemd user timer on Linux running `logrotate`.
|
|
99
|
+
Re-running setup on an already-wired machine reports healthy.
|
|
100
|
+
|
|
101
|
+
`configure_logging(...)` only creates and opens the log file; it never writes
|
|
102
|
+
rotation assets or invokes launchd/systemd. No `/etc` configuration, no sudo,
|
|
103
|
+
and no system rotation daemon ever touches these files, so rotated/recreated
|
|
104
|
+
logs always stay owned by the producing user.
|
|
99
105
|
|
|
100
106
|
## CLI
|
|
101
107
|
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_configure_logging.py
RENAMED
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from tempfile import TemporaryDirectory
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
|
-
from instrukt_ai_logging import InstruktAILogger, configure_logging, get_logger
|
|
8
|
+
from instrukt_ai_logging import InstruktAILogger, configure_logging, get_logger
|
|
9
9
|
|
|
10
10
|
# Log markers shared by each test and its assertions — named constants per
|
|
11
11
|
# software-development/procedure/snapshot-testing (no bare literals in content
|
|
@@ -41,8 +41,6 @@ _FIELD_SESSION = f"session={_KV_SESSION}"
|
|
|
41
41
|
_FIELD_N = f"n={_KV_N}"
|
|
42
42
|
|
|
43
43
|
_APP_NAME = "teleclaude"
|
|
44
|
-
_ROTATION_PROBLEM_MARKER = "log rotation ensure problem"
|
|
45
|
-
_ROTATION_FAILURE_REASON = "no session bus"
|
|
46
44
|
|
|
47
45
|
|
|
48
46
|
@pytest.fixture()
|
|
@@ -121,33 +119,6 @@ def test_configure_logging_fails_fast_when_file_unwritable(isolated_logging, mon
|
|
|
121
119
|
os.chmod(log_path, 0o644)
|
|
122
120
|
|
|
123
121
|
|
|
124
|
-
class _FakeFailingCompletedProcess:
|
|
125
|
-
def __init__(self) -> None:
|
|
126
|
-
self.returncode = 1
|
|
127
|
-
self.stderr = _ROTATION_FAILURE_REASON
|
|
128
|
-
self.stdout = ""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def test_configure_logging_warns_without_raising_when_rotation_ensure_fails(isolated_logging, monkeypatch):
|
|
132
|
-
with TemporaryDirectory() as tmp:
|
|
133
|
-
monkeypatch.setenv("XDG_STATE_HOME", tmp)
|
|
134
|
-
monkeypatch.setenv("TELECLAUDE_LOG_LEVEL", "INFO")
|
|
135
|
-
monkeypatch.setenv("TELECLAUDE_THIRD_PARTY_LOG_LEVEL", "WARNING")
|
|
136
|
-
|
|
137
|
-
def _fake_run(args):
|
|
138
|
-
return _FakeFailingCompletedProcess()
|
|
139
|
-
|
|
140
|
-
monkeypatch.setattr(install, "_run_scheduler_command", _fake_run)
|
|
141
|
-
|
|
142
|
-
# A rotation-ensure failure must never crash logging — it's surfaced
|
|
143
|
-
# as a WARNING through the configured logger, not raised.
|
|
144
|
-
log_path = configure_logging(_APP_NAME)
|
|
145
|
-
|
|
146
|
-
content = _read_text(log_path)
|
|
147
|
-
assert _ROTATION_PROBLEM_MARKER in content
|
|
148
|
-
assert _ROTATION_FAILURE_REASON in content
|
|
149
|
-
|
|
150
|
-
|
|
151
122
|
def test_configure_logging_resolves_xdg_state_home_location(isolated_logging, monkeypatch):
|
|
152
123
|
with TemporaryDirectory() as tmp:
|
|
153
124
|
monkeypatch.setenv("XDG_STATE_HOME", tmp)
|
|
@@ -223,6 +223,58 @@ def test_ensure_rotation_tolerates_already_bootstrapped_launchd(
|
|
|
223
223
|
assert problems == []
|
|
224
224
|
|
|
225
225
|
|
|
226
|
+
@pytest.mark.functional
|
|
227
|
+
def test_main_treats_print_confirmed_launchd_eio_as_healthy(
|
|
228
|
+
rotation_env: Path, monkeypatch: pytest.MonkeyPatch
|
|
229
|
+
) -> None:
|
|
230
|
+
monkeypatch.setattr(sys, "platform", "darwin")
|
|
231
|
+
|
|
232
|
+
def _fake_run(args: list[str]) -> _FakeCompletedProcess:
|
|
233
|
+
if args[1] == "bootstrap":
|
|
234
|
+
return _FakeCompletedProcess(returncode=5, stderr="Bootstrap failed: 5: Input/output error")
|
|
235
|
+
return _FakeCompletedProcess(returncode=0)
|
|
236
|
+
|
|
237
|
+
monkeypatch.setattr(install, "_run_scheduler_command", _fake_run)
|
|
238
|
+
|
|
239
|
+
install.main()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@pytest.mark.functional
|
|
243
|
+
def test_main_reports_unconfirmed_launchd_eio(rotation_env: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
244
|
+
monkeypatch.setattr(sys, "platform", "darwin")
|
|
245
|
+
|
|
246
|
+
def _fake_run(args: list[str]) -> _FakeCompletedProcess:
|
|
247
|
+
if args[1] == "bootstrap":
|
|
248
|
+
return _FakeCompletedProcess(returncode=5, stderr="Bootstrap failed: 5: Input/output error")
|
|
249
|
+
return _FakeCompletedProcess(returncode=1)
|
|
250
|
+
|
|
251
|
+
monkeypatch.setattr(install, "_run_scheduler_command", _fake_run)
|
|
252
|
+
|
|
253
|
+
with pytest.raises(SystemExit) as exc_info:
|
|
254
|
+
install.main()
|
|
255
|
+
|
|
256
|
+
assert exc_info.value.code == 1
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@pytest.mark.functional
|
|
260
|
+
def test_main_reports_launchd_eio_when_discriminator_times_out(
|
|
261
|
+
rotation_env: Path, monkeypatch: pytest.MonkeyPatch
|
|
262
|
+
) -> None:
|
|
263
|
+
monkeypatch.setattr(sys, "platform", "darwin")
|
|
264
|
+
|
|
265
|
+
def _fake_run(args: list[str]) -> _FakeCompletedProcess:
|
|
266
|
+
if args[1] == "bootstrap":
|
|
267
|
+
return _FakeCompletedProcess(returncode=5, stderr="Bootstrap failed: 5: Input/output error")
|
|
268
|
+
raise subprocess.TimeoutExpired(cmd=args, timeout=install._SCHEDULER_COMMAND_TIMEOUT_S)
|
|
269
|
+
|
|
270
|
+
monkeypatch.setattr(install, "_run_scheduler_command", _fake_run)
|
|
271
|
+
|
|
272
|
+
with pytest.raises(SystemExit) as exc_info:
|
|
273
|
+
install.main()
|
|
274
|
+
|
|
275
|
+
assert exc_info.value.code == 1
|
|
276
|
+
|
|
277
|
+
|
|
226
278
|
def test_main_prints_status_and_exits_zero_when_healthy(
|
|
227
279
|
rotation_env: Path,
|
|
228
280
|
successful_subprocess: list[list[str]],
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/__init__.py
RENAMED
|
File without changes
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/cli.py
RENAMED
|
File without changes
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/instrukt_ai_logging/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_log_aggregation.py
RENAMED
|
File without changes
|
{instruktai_python_logger-0.6.2 → instruktai_python_logger-0.6.4}/tests/test_trace_logging.py
RENAMED
|
File without changes
|