Docs / Libraries
Python
Install the justlog3 package, log to a file and to the cloud, levels, batching and shutdown behaviour.
The justlog3 package writes log lines to a file in batches and, once you set an API token, sends them to JustLog3 Cloud from a background thread. log() never waits for the disk or the network.
Install
pip install justlog3
Python 3.8 or newer. httpx, used for cloud sending, is installed with the package. Source and benchmarks: github.com/OAzizjon/justlog3.
Log to a file
from justlog3 import Logger
logger = Logger('app.log')
logger.log('Hi...')
logger.log('debug', off_console=True)
logger.log('There is some error!', red=True)
logger.log('OK', green=True)
logger.log('There is critical error!', red=True, custom_prefix='CRITICAL!!')
The console shows colored lines; app.log gets one line per call with a prefix and a local timestamp with milliseconds:
GREY:2026-10-05 14:03:12.517 - Hi...
RED:2026-10-05 14:03:12.518 - There is some error!
GREEN:2026-10-05 14:03:12.518 - OK
Send to JustLog3 Cloud
import os
from justlog3 import Logger, set_api_token
set_api_token(os.environ['JUSTLOG3_TOKEN'], url='https://jl3-cloud.site/api/logs/')
logger = Logger('app.log')
logger.log('This line goes to the file and to the cloud')
Call set_api_token() once, before or after creating loggers. Keep the token in an environment variable rather than in code.
- Lines are sent every
flush_intervalseconds (default 5), or sooner oncecloud_cycleslines (default 75) are waiting. - A request carries at most 5,000 lines and 512 KB of text; bodies from 1 KB are gzip-compressed.
- Each logger keeps up to 10,000 unsent lines; beyond that the oldest are dropped with a single warning.
- No answer or HTTP 5xx: the batch is resent with the same sequence number, so the server stores it once. The wait starts at 5 s and doubles up to 5 minutes.
- HTTP 429: nothing is sent until
Retry-After; lines stay buffered. - HTTP 401 / 403: cloud sending stops, files keep being written. Call
set_api_token()again with a valid token. - On exit the remaining lines are sent, waiting at most
timeoutseconds.
set_api_token(token, *, url=..., flush_interval=5.0, timeout=5.0) raises ValueError for an empty token.
Levels
from justlog3 import BasicLogger
logger = BasicLogger('app.log', console_level='INFO')
logger.debug('cache warmed') # file and cloud only: below INFO
logger.info('server started')
logger.warning('disk 85% full')
logger.error('payment failed')
logger.critical('database is down')
console_level only filters the console. Every line still goes to the file and the cloud.
Shutdown and signals
- Normal exit: every logger is flushed by an
atexithook. - SIGTERM (
docker stop, systemd,kill): JustLog3 turns the signal into a normal exit so the flush runs. Calloff_signal_handler()before creating any logger to keep your own handler. kill -9or a power cut loses what is still in the buffer: at mostcycles - 1lines (default 49).- Call
shutdown()yourself beforeos._exit().
Logger options
| Parameter | Default | Meaning |
|---|---|---|
filename |
'app.log' |
.log is added if missing |
with_time |
True |
timestamp in every line |
filemode |
'a' |
'w' empties the file once, on creation |
cycles |
50 |
lines per disk write |
cloud_cycles |
75 |
waiting lines that wake the cloud sender |
off_sigmask |
False |
don't hold back SIGTERM during writes (Linux, macOS) |