loki-reader-core 0.2.3__tar.gz → 0.2.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.
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/PKG-INFO +1 -1
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/pyproject.toml +1 -1
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/__init__.py +1 -1
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/client.py +21 -13
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/tests/test_client.py +32 -16
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/.gitignore +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/README.md +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/build-publish.sh +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/dev-requirements.txt +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/exceptions.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/__init__.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/log_entry.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/log_stream.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/metric_sample.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/metric_series.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/query_result.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/query_stats.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/utils.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/tests/__init__.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/tests/test_models.py +0 -0
- {loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: loki-reader-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Python library for querying Grafana Loki logs via REST API
|
|
5
5
|
Project-URL: Homepage, https://github.com/jmazzahacks/loki-reader-core
|
|
6
6
|
Project-URL: Issues, https://github.com/jmazzahacks/loki-reader-core/issues
|
|
@@ -6,7 +6,7 @@ from .client import LokiClient
|
|
|
6
6
|
from .exceptions import LokiAuthError, LokiConnectionError, LokiError, LokiQueryError
|
|
7
7
|
from .models import LogEntry, LogStream, MetricSample, MetricSeries, QueryResult, QueryStats
|
|
8
8
|
|
|
9
|
-
__version__ = "0.2.
|
|
9
|
+
__version__ = "0.2.4"
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"LokiClient",
|
|
@@ -187,7 +187,7 @@ class LokiClient:
|
|
|
187
187
|
|
|
188
188
|
self._session: Optional[requests.Session] = None
|
|
189
189
|
self._app_label_cache: dict[str, str] = {}
|
|
190
|
-
self._severity_label_cache: Optional[str] =
|
|
190
|
+
self._severity_label_cache: dict[str, Optional[str]] = {}
|
|
191
191
|
|
|
192
192
|
@property
|
|
193
193
|
def session(self) -> requests.Session:
|
|
@@ -312,24 +312,32 @@ class LokiClient:
|
|
|
312
312
|
f"({', '.join(APP_LABEL_NAMES)}). Use logql param for custom labels."
|
|
313
313
|
)
|
|
314
314
|
|
|
315
|
-
def _find_severity_label(self) -> Optional[str]:
|
|
316
|
-
"""Discover which label name is used
|
|
315
|
+
def _find_severity_label(self, app_label: str, app_value: str) -> Optional[str]:
|
|
316
|
+
"""Discover which severity label name is used by a specific app.
|
|
317
317
|
|
|
318
|
-
|
|
319
|
-
|
|
318
|
+
Queries the actual stream labels for the given app and checks
|
|
319
|
+
which severity label name appears. This avoids false matches
|
|
320
|
+
from other apps using a different severity label.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
app_label: The label name for the application (e.g. "application").
|
|
324
|
+
app_value: The application name (e.g. "materia-server").
|
|
320
325
|
|
|
321
326
|
Returns:
|
|
322
|
-
The severity label name, or None if not found.
|
|
327
|
+
The severity label name for this app, or None if not found.
|
|
323
328
|
"""
|
|
324
|
-
if self._severity_label_cache
|
|
325
|
-
return self._severity_label_cache
|
|
329
|
+
if app_value in self._severity_label_cache:
|
|
330
|
+
return self._severity_label_cache[app_value]
|
|
331
|
+
|
|
332
|
+
series = self.get_series(match=['{' + f'{app_label}="{app_value}"' + '}'])
|
|
326
333
|
|
|
327
334
|
for label_name in SEVERITY_LABEL_NAMES:
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
335
|
+
for s in series:
|
|
336
|
+
if label_name in s:
|
|
337
|
+
self._severity_label_cache[app_value] = label_name
|
|
338
|
+
return label_name
|
|
332
339
|
|
|
340
|
+
self._severity_label_cache[app_value] = None
|
|
333
341
|
return None
|
|
334
342
|
|
|
335
343
|
def query(
|
|
@@ -376,7 +384,7 @@ class LokiClient:
|
|
|
376
384
|
app_label = self._find_app_label(app)
|
|
377
385
|
selector = f'{app_label}="{app}"'
|
|
378
386
|
if severity is not None:
|
|
379
|
-
sev_label = self._find_severity_label()
|
|
387
|
+
sev_label = self._find_severity_label(app_label, app)
|
|
380
388
|
if sev_label:
|
|
381
389
|
regex = _build_severity_regex(severity)
|
|
382
390
|
selector += f', {sev_label}=~"{regex}"'
|
|
@@ -75,7 +75,7 @@ class TestLokiClientInit:
|
|
|
75
75
|
def test_init_label_caches_empty(self) -> None:
|
|
76
76
|
client = LokiClient(base_url="http://localhost:3100")
|
|
77
77
|
assert client._app_label_cache == {}
|
|
78
|
-
assert client._severity_label_cache
|
|
78
|
+
assert client._severity_label_cache == {}
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
class TestLokiClientSession:
|
|
@@ -474,19 +474,32 @@ class TestLabelDiscovery:
|
|
|
474
474
|
with pytest.raises(ValueError, match="Could not find 'myapp'"):
|
|
475
475
|
client._find_app_label("myapp")
|
|
476
476
|
|
|
477
|
-
def
|
|
477
|
+
def test_find_severity_label_from_series(self) -> None:
|
|
478
478
|
client = LokiClient(base_url="http://localhost:3100")
|
|
479
|
-
with patch.object(client, "
|
|
480
|
-
|
|
481
|
-
|
|
479
|
+
with patch.object(client, "get_series") as mock_gs:
|
|
480
|
+
mock_gs.return_value = [
|
|
481
|
+
{"application": "myapp", "severity": "info", "logger": "root"},
|
|
482
|
+
]
|
|
483
|
+
result = client._find_severity_label("application", "myapp")
|
|
484
|
+
assert result == "severity"
|
|
485
|
+
mock_gs.assert_called_once_with(match=['{application="myapp"}'])
|
|
486
|
+
|
|
487
|
+
def test_find_severity_label_level(self) -> None:
|
|
488
|
+
client = LokiClient(base_url="http://localhost:3100")
|
|
489
|
+
with patch.object(client, "get_series") as mock_gs:
|
|
490
|
+
mock_gs.return_value = [
|
|
491
|
+
{"application": "myapp", "level": "info", "logger": "root"},
|
|
492
|
+
]
|
|
493
|
+
result = client._find_severity_label("application", "myapp")
|
|
482
494
|
assert result == "level"
|
|
483
|
-
mock_glv.assert_called_once_with("level")
|
|
484
495
|
|
|
485
496
|
def test_find_severity_label_none(self) -> None:
|
|
486
497
|
client = LokiClient(base_url="http://localhost:3100")
|
|
487
|
-
with patch.object(client, "
|
|
488
|
-
|
|
489
|
-
|
|
498
|
+
with patch.object(client, "get_series") as mock_gs:
|
|
499
|
+
mock_gs.return_value = [
|
|
500
|
+
{"application": "myapp", "logger": "root"},
|
|
501
|
+
]
|
|
502
|
+
result = client._find_severity_label("application", "myapp")
|
|
490
503
|
assert result is None
|
|
491
504
|
|
|
492
505
|
def test_label_discovery_cached(self) -> None:
|
|
@@ -502,13 +515,16 @@ class TestLabelDiscovery:
|
|
|
502
515
|
|
|
503
516
|
def test_severity_label_cached(self) -> None:
|
|
504
517
|
client = LokiClient(base_url="http://localhost:3100")
|
|
505
|
-
with patch.object(client, "
|
|
506
|
-
|
|
518
|
+
with patch.object(client, "get_series") as mock_gs:
|
|
519
|
+
mock_gs.return_value = [
|
|
520
|
+
{"application": "myapp", "severity": "info"},
|
|
521
|
+
]
|
|
507
522
|
|
|
508
|
-
client._find_severity_label()
|
|
509
|
-
client._find_severity_label()
|
|
523
|
+
client._find_severity_label("application", "myapp")
|
|
524
|
+
client._find_severity_label("application", "myapp")
|
|
510
525
|
|
|
511
|
-
|
|
526
|
+
# Only called once - second call uses cache
|
|
527
|
+
mock_gs.assert_called_once()
|
|
512
528
|
|
|
513
529
|
|
|
514
530
|
class TestMergeStreams:
|
|
@@ -639,14 +655,14 @@ class TestLokiClientQueryRedesign:
|
|
|
639
655
|
def test_query_app_with_severity(self) -> None:
|
|
640
656
|
client = LokiClient(base_url="http://localhost:3100")
|
|
641
657
|
with patch.object(client, "_find_app_label", return_value="application"), \
|
|
642
|
-
patch.object(client, "_find_severity_label", return_value="
|
|
658
|
+
patch.object(client, "_find_severity_label", return_value="severity"), \
|
|
643
659
|
patch.object(client, "query_range") as mock_qr:
|
|
644
660
|
mock_qr.return_value = self._make_multi_stream_result()
|
|
645
661
|
|
|
646
662
|
client.query(app="myapp", severity="error")
|
|
647
663
|
|
|
648
664
|
args = mock_qr.call_args
|
|
649
|
-
assert args.kwargs["logql"] == '{application="myapp",
|
|
665
|
+
assert args.kwargs["logql"] == '{application="myapp", severity=~"error|fatal|critical"}'
|
|
650
666
|
|
|
651
667
|
def test_query_app_since_minutes(self) -> None:
|
|
652
668
|
client = LokiClient(base_url="http://localhost:3100")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/metric_sample.py
RENAMED
|
File without changes
|
{loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/metric_series.py
RENAMED
|
File without changes
|
{loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/query_result.py
RENAMED
|
File without changes
|
{loki_reader_core-0.2.3 → loki_reader_core-0.2.4}/src/loki_reader_core/models/query_stats.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|