Skip to content

Commit 3e7e604

Browse files
committed
docs: Describe configuration and limitations
1 parent 664b9ed commit 3e7e604

6 files changed

Lines changed: 92 additions & 34 deletions

File tree

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
coverage:
22
coverage run -m unittest discover tests/
33
coverage report -m
4+
5+
docs:
6+
pdoc -d=google vlogs_handler

README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
# victorialogs-handler
1+
# python-victorialogs-handler
22

33
A high-performance Python log handler for VictoriaLogs.
44

5-
[![release](https://img.shields.io/pypi/v/python-victorialogs-handler?label=release)](https://pypi.org/project/python-victorialogs-handler/)
6-
[![python](https://img.shields.io/pypi/pyversions/python-victorialogs-handler)](https://pypi.org/project/python-victorialogs-handler/)
5+
[![release](https://img.shields.io/pypi/v/victorialogs-handler?label=release)](https://pypi.org/project/victorialogs-handler/)
6+
[![python](https://img.shields.io/pypi/pyversions/victorialogs-handler)](https://pypi.org/project/victorialogs-handler/)
77
[![CI/CD](https://github.com/ErikKalkoken/python-victorialogs-handler/actions/workflows/cicd.yaml/badge.svg)](https://github.com/ErikKalkoken/python-victorialogs-handler/actions/workflows/cicd.yaml)
88
[![codecov](https://codecov.io/gh/ErikKalkoken/python-victorialogs-handler/graph/badge.svg?token=2pPb3lid2k)](https://codecov.io/gh/ErikKalkoken/python-victorialogs-handler)
99
[![license](https://img.shields.io/badge/license-MIT-green)](https://gitlab.com/ErikKalkoken/python-victorialogs-handler/-/blob/master/LICENSE)
1010

11-
> [!IMPORTANT]
12-
> STATUS: In development. The API may still change.
13-
1411
## Description
1512

1613
**victorialogs-handler** is a high-performance Python log handler tailored for [VictoriaLogs](https://victoriametrics.com/products/victorialogs/). It integrates seamlessly with Python’s native logging module, allowing you to stream log events to a VictoriaLogs instance with minimal configuration.

src/vlogs_handler/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
from .handler import VictoriaLogsHandler # noqa: F401
1212

1313
__title__ = "VictoriaLogs Handler"
14-
__version__ = "0.1.0a1"
14+
__version__ = "0.1.0a2"
1515

1616
__all__ = ["VictoriaLogsHandler"]

src/vlogs_handler/handler.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,43 @@ class VictoriaLogsHandler(logging.Handler):
4949
"""A handler class which dispatches logging records to a VictoriaLogs server.
5050
5151
Args:
52-
batch_size: New logs are submitted immediately once this threshold is reached.
53-
flush_interval: New logs are submitted every x seconds.
52+
batch_size: Triggers flushing the buffer once this threshold is reached.
5453
buffer_size: Maximum number of logs the buffer can hold.
5554
If buffer_size <= 0, the size is unlimited (not recommended).
5655
When the buffer is full any new logs will be discarded.
57-
100 000 logs consume approx. 80-100 MB of RAM.
58-
Tip: The buffer should be large enough to hold incoming logs
59-
while the log server is down for regular maintenance.
56+
50 000 logs consume approx. 40-50 MB of RAM.
57+
Note that each Python process the handler is running on has it's own buffer.
58+
Tip: At a minimum the combined buffer of all handlers should be
59+
large enough to hold incoming logs while the last chunk
60+
is being transferred to the log server.
61+
Ideally, it should be able to hold incoming logs while
62+
the vlogs server is down for regular maintenance.
6063
chunk_size: Maximum number of logs send per request to the log server.
64+
flush_interval: Triggers flushing the buffer at an interval of x seconds.
6165
record_to_stream: A function that returns the value for the `stream`field
6266
for a log record. The default will return the name of the top package.
6367
request_timeout: Timeout when sending a request to the vlogs server in seconds.
68+
shutdown_timeout: Timeout when waiting for the worker
69+
to flush the buffer during shutdown.
6470
start_worker: Whether to start the worker at initialization.
6571
Alternatively, the worker can be started later by calling `start()`.
66-
shutdown_timeout: Timeout when waiting for the worker to shut down.
6772
url: URL of the vlogs server, e.g. `"http://localhost:9428"`
73+
74+
Raises:
75+
ValueError: If the validation of an argument fails.
76+
RuntimeError: If the handler is not started in a module.
6877
"""
6978

7079
def __init__(
7180
self,
81+
*,
7282
batch_size: int = 125,
73-
buffer_size: int = 100_000,
83+
buffer_size: int = 50_000,
7484
chunk_size: int = 1_000,
7585
flush_interval: float = 5.0,
7686
record_to_stream: Optional[Callable[[logging.LogRecord], str]] = None,
7787
request_timeout: float = 3.0,
78-
shutdown_timeout: float = 2.0,
88+
shutdown_timeout: float = 4.0,
7989
start_worker: bool = True,
8090
url: str = "http://localhost:9428",
8191
):

src/vlogs_handler/technical.md

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,80 @@
1-
# Technical overview
1+
# Technical documentation
22

3-
This section gives a technical overview of how the vlogs handler works.
3+
This section describes how the handler works and how it can be configured.
44

55
## Process Flow
66

77
The high-level process flow of the vlogs handler is as follows:
88

9-
1. When a a log event is received, it is converted into JSON and stored
10-
in the buffer
11-
1. At the tick of an interval (e.g. 5 seconds) or when a threshold is reached
12-
(e.g. 125 logs) a background worker starts the process of submitting logs
13-
from the buffer to the log server
14-
1. Logs are combined into chunks (e.g. 1.000 logs per request)
15-
and then submitted to the log server using vlog's the JSON Stream API
9+
- When a log event is received, it is converted into JSON and stored in the buffer.
10+
- When the logs are flushed, they are transferred to the log server by a background worker.
11+
- The flushing of the buffer is triggered when the `flush_interval` expires (e.g. every 5 seconds) or when more then `batch_size` logs (e.g. 125) have been received.
12+
- Logs are combined into chunks defined by `chunk_size` (e.g. 1.000 logs per request) and then submitted to the log server using the JSON Stream API.
1613

1714
## Failure behavior
1815

1916
The failure behavior of the handler in key scenarios is as follows:
2017

21-
- In case the submission to the log server fails
22-
(e.g. the server is temporarily down) the logs will be stored
23-
in the buffer for later retry
24-
- If the buffer is full, new log events will be discarded
25-
and raise a exceptions (depending on logging configuration)
26-
- The handler will make a final attempt to submit remaining logs during shutdown.
27-
If that fails those logs will written to stderr.
18+
- In case the submission to the log server fails (e.g. the server is temporarily down) the logs will be stored in the buffer for later retry.
19+
- If the buffer is full, new log events will be discarded and raise a exceptions (depending on logging configuration).
20+
- The handler will make a final attempt to submit remaining logs during shutdown. If that fails those logs will written to stderr.
2821

29-
## LogRecord fields
22+
## Configuration
23+
24+
This section describes how the handler and it's logger can be configured.
25+
26+
### Handler configuration
27+
28+
> [!TIP]
29+
> The handler comes pre-configured with sensible defaults and often does not need to be configured.
30+
31+
The handler can be configured through keyword argument of the handler's constructor.
32+
All arguments are optional and will be set to sensible defaults when not provided.
33+
34+
For example the size of the log buffer can be configured by setting `buffer_size`:
35+
36+
```python
37+
vlogs_handler = VictoriaLogsHandler(buffer_size=100_000)
38+
```
39+
40+
For a full description of all arguments please see `VictoriaLogsHandler`.
41+
42+
### Handler logging
43+
44+
The vlogs handler has it's own logger and which can be found under the name `vlogs_handler`.
45+
It will log issues related to transferring logs to the vlogs server.
46+
47+
For example this will attach a console handler to the logger with warning level:
48+
49+
```python
50+
console_handler = logging.StreamHandler()
51+
console_handler.setLevel(logging.DEBUG)
52+
vlogs_logger = logging.getLogger("vlogs_handler")
53+
vlogs_handler.setLevel(logging.WARNING)
54+
vlogs_logger.addHandler(console_handler)
55+
```
56+
57+
> [!NOTE]
58+
> A vlogs handler instance can not be attached to this logger, as this would create an infinite loop.
59+
60+
## Limitations
61+
62+
The handler was designed for a specific scenario:
63+
64+
- Transfer logs from a Django server to a VictoriaLogs instance running on the same server
65+
- Our focus is on applications logs over server logs (i.e. logs from Django apps over logs from the Django server itself)
66+
- The handler should be easy to install and use
67+
68+
Our design choices result in a few limitations:
69+
70+
- The buffer is kept in memory, which means that there is a risk that some logs are lost when the Django server itself has a failure. Because of that limitation we recommend not to rely on the vlogs handler alone, but to always use a log file as backup.
71+
- The handler does not implement HTTP authentication or backoff and retry logic for HTTP requests. It is therefore currently not suitable to be used with a remote VictoriaLogs instance.
72+
73+
## Data Model
74+
75+
This section describes the structure of the data that is transferred to the vlogs server.
76+
77+
### LogRecord fields
3078

3179
The following fields will be transferred for each log event. They are derived from Python's [LogRecord](https://docs.python.org/3/library/logging.html#logrecord-objects):
3280

@@ -44,7 +92,7 @@ Name | Description | Example | Optional
4492

4593
In addition any custom `extras' fields will be added as they are encountered.
4694

47-
## VictoriaLogs special fields
95+
### VictoriaLogs special fields
4896

4997
VictoriaLogs handles three fields in a special way:
5098

tests/test_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_should_init_with_defaults(self):
3232
self.assertEqual(handler._chunk_size, 1000)
3333
self.assertEqual(handler._flush_interval, 5.0)
3434
self.assertEqual(handler._request_timeout, 3.0)
35-
self.assertEqual(handler._shutdown_timeout, 2.0)
35+
self.assertEqual(handler._shutdown_timeout, 4.0)
3636
self.assertEqual(
3737
handler._vlogs_url,
3838
"http://localhost:9428/insert/jsonline"

0 commit comments

Comments
 (0)