scietex.log_aggregator_service
scietex.log_aggregator_service is a scietex.service worker that merges the
per-worker log streams of the configured services into one shared stream. Each
scietex.service worker writes its own stream
(scietex:{service}:{instance_id}:log); this service tails all of them and
copies every entry into a single target stream (scietex:log by default),
stamping each entry with a source field ({service}:{instance_id}) so
consumers can tell which worker emitted it.
The aggregator is the sole writer of the target stream, so it owns both the
MAXLEN ~ trim and the whole-key EXPIRE. The API backend reads that stream
for the system log viewer and no longer trims it.
Python ≥ 3.10 · License: MIT
How it works
per-worker log streams shared stream viewer
scietex:{svc}:{inst}:log ─┐
scietex:{svc2}:{inst}:log ─┤ XREAD (multi-key) ┌────────────────┐ GET /logs/ ─► LogViewer
scietex:{svcN}:{inst}:log ─┘ ───────────────► │ scietex:log │ GET /logs/stream (SSE) (Source col)
│ XADD MAXLEN ~ │
▲ each writer owns its stream │ EXPIRE ttl │
│ (worker heartbeat refreshes its TTL) └────────────────┘
▲ single owner
┌───────────────┴────────────────┐
│ LogAggregatorService worker │
│ (reads scietex:{agg}:config) │
└─────────────────────────────────┘
- A single supervisor loop (not one task per stream) tails every source with
a multi-key
XREAD, so the merge is natural and there is no task fan-out. - A periodic
SCAN(scietex:{service}:*:log) picks up workers that appear or disappear; the source set is rebuilt in place. - The target stream's TTL is refreshed on a timer (Valkey
EXPIREsets a TTL on the key;XADDdoes not refresh it). - The aggregator's own service is excluded from the source set, so its logs do not loop back into the stream it writes.
Installation
pip install scietex.log_aggregator_service
This pulls in scietex.service[valkey] (the worker framework and its Valkey
transport).
Quick start
1. Write a configuration file
The service reads log_aggregator.yml from a log_aggregator/ subdirectory of
its config directory. Create it by hand, or let the service generate defaults on
first run:
source_services:
- ModbusService
exclude_services:
- LogAggregatorService
target_stream: scietex:log
max_len: 100000
ttl_seconds: 604800
batch_size: 200
block_ms: 1000
scan_interval: 15.0
2. Run the service
start-log-aggregator --conf-dir /etc/scietex
The service resolves its config directory automatically when --conf-dir is
omitted. It runs in the foreground until it receives SIGINT or SIGTERM.
3. Register it with the backend
The backend is the config authority: register the service so it can deliver the
log_aggregator section (source services, target stream, max_len, ttl):
curl -X POST http://localhost:8000/api/v1/services/discovered/LogAggregatorService/register
Configuration at a glance
| Setting | Default | Meaning |
|---|---|---|
source_services |
[] |
Service names whose per-worker log streams are aggregated |
exclude_services |
[] |
Names removed from the source set (self-exclusion) |
target_stream |
scietex:log |
Shared stream the aggregator writes |
max_len |
100000 |
MAXLEN ~ applied on each write (0 disables) |
ttl_seconds |
604800 |
Whole-key TTL refreshed on a timer (0 disables) |
batch_size |
200 |
Entries per XREAD |
block_ms |
1000 |
XREAD block timeout |
scan_interval |
15.0 |
Seconds between source-set SCANs |
Development
Dependencies are managed with uv; checks and tests run through tox:
uv sync --all-extras
uv run tox # format, lint, type, py314
uv run tox -e py314 # tests only
Metadata
Release files for scietex.log-aggregator-service 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| scietex_log_aggregator_service-0.1.1.tar.gz | 15.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| scietex_log_aggregator_service-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.3 kB
Release files / scietex_log_aggregator_service-0.1.1.tar.gz
| Download URL | scietex_log_aggregator_service-0.1.1.tar.gz |
|---|---|
| Size | 15.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4a742a2a482c073caf856737ec3c8fa0eae0cb4775f8c2c9668dcb9bdaed08c7
|
|
BLAKE2b-256 checksum How to use checksums |
71ecdc777f5269c03bfc5616f0ebe9017643f89f35cb7a92b483ebea67c243be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / scietex_log_aggregator_service-0.1.1-py3-none-any.whl
| Download URL | scietex_log_aggregator_service-0.1.1-py3-none-any.whl |
|---|---|
| Size | 12.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e9e2673840bdabf0d0aff2f9a91f5058fdb0db205bcddcff5e8aa7c2295ec0c6
|
|
BLAKE2b-256 checksum How to use checksums |
f02cc7f23cf9aea9509d0620c5026d4707ebfd7f41bc8fc17acb2eb71d70c500
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency log