loki-reader-core 0.2.1__tar.gz → 0.2.2__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.1 → loki_reader_core-0.2.2}/PKG-INFO +1 -1
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/pyproject.toml +1 -1
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/__init__.py +1 -1
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/client.py +18 -2
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/tests/test_client.py +25 -5
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/.gitignore +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/README.md +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/build-publish.sh +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/dev-requirements.txt +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/exceptions.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/__init__.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/log_entry.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/log_stream.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/metric_sample.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/metric_series.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/query_result.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/query_stats.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/utils.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/tests/__init__.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/tests/test_models.py +0 -0
- {loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/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.2
|
|
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.2"
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"LokiClient",
|
|
@@ -269,6 +269,20 @@ class LokiClient:
|
|
|
269
269
|
|
|
270
270
|
return data
|
|
271
271
|
|
|
272
|
+
def _discovery_time_range(self) -> tuple[int, int]:
|
|
273
|
+
"""Get a 30-day time range for label discovery queries.
|
|
274
|
+
|
|
275
|
+
Without a time range, Loki's label API only returns labels for
|
|
276
|
+
recently active streams. Using a 30-day window ensures we find
|
|
277
|
+
apps that haven't logged in a while.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Tuple of (start_ns, end_ns) covering the last 30 days.
|
|
281
|
+
"""
|
|
282
|
+
end = now_ns()
|
|
283
|
+
start = end - (30 * 24 * NANOSECONDS_PER_HOUR)
|
|
284
|
+
return (start, end)
|
|
285
|
+
|
|
272
286
|
def _find_app_label(self, app_value: str) -> str:
|
|
273
287
|
"""Discover which label name contains the given app value.
|
|
274
288
|
|
|
@@ -287,8 +301,9 @@ class LokiClient:
|
|
|
287
301
|
if app_value in self._app_label_cache:
|
|
288
302
|
return self._app_label_cache[app_value]
|
|
289
303
|
|
|
304
|
+
start, end = self._discovery_time_range()
|
|
290
305
|
for label_name in APP_LABEL_NAMES:
|
|
291
|
-
values = self.get_label_values(label_name)
|
|
306
|
+
values = self.get_label_values(label_name, start=start, end=end)
|
|
292
307
|
if app_value in values:
|
|
293
308
|
self._app_label_cache[app_value] = label_name
|
|
294
309
|
return label_name
|
|
@@ -310,8 +325,9 @@ class LokiClient:
|
|
|
310
325
|
if self._severity_label_cache is not None:
|
|
311
326
|
return self._severity_label_cache
|
|
312
327
|
|
|
328
|
+
start, end = self._discovery_time_range()
|
|
313
329
|
for label_name in SEVERITY_LABEL_NAMES:
|
|
314
|
-
values = self.get_label_values(label_name)
|
|
330
|
+
values = self.get_label_values(label_name, start=start, end=end)
|
|
315
331
|
if values:
|
|
316
332
|
self._severity_label_cache = label_name
|
|
317
333
|
return label_name
|
|
@@ -453,12 +453,16 @@ class TestLabelDiscovery:
|
|
|
453
453
|
mock_glv.return_value = ["myapp", "otherapp"]
|
|
454
454
|
result = client._find_app_label("myapp")
|
|
455
455
|
assert result == "application"
|
|
456
|
-
mock_glv.
|
|
456
|
+
mock_glv.assert_called_once()
|
|
457
|
+
args = mock_glv.call_args
|
|
458
|
+
assert args.args[0] == "application"
|
|
459
|
+
assert "start" in args.kwargs
|
|
460
|
+
assert "end" in args.kwargs
|
|
457
461
|
|
|
458
462
|
def test_find_app_label_job(self) -> None:
|
|
459
463
|
client = LokiClient(base_url="http://localhost:3100")
|
|
460
464
|
with patch.object(client, "get_label_values") as mock_glv:
|
|
461
|
-
def side_effect(label: str) -> list[str]:
|
|
465
|
+
def side_effect(label: str, start: int = None, end: int = None) -> list[str]:
|
|
462
466
|
if label == "job":
|
|
463
467
|
return ["myapp", "worker"]
|
|
464
468
|
return []
|
|
@@ -480,7 +484,11 @@ class TestLabelDiscovery:
|
|
|
480
484
|
mock_glv.return_value = ["info", "error", "warn"]
|
|
481
485
|
result = client._find_severity_label()
|
|
482
486
|
assert result == "level"
|
|
483
|
-
mock_glv.
|
|
487
|
+
mock_glv.assert_called_once()
|
|
488
|
+
args = mock_glv.call_args
|
|
489
|
+
assert args.args[0] == "level"
|
|
490
|
+
assert "start" in args.kwargs
|
|
491
|
+
assert "end" in args.kwargs
|
|
484
492
|
|
|
485
493
|
def test_find_severity_label_none(self) -> None:
|
|
486
494
|
client = LokiClient(base_url="http://localhost:3100")
|
|
@@ -498,7 +506,7 @@ class TestLabelDiscovery:
|
|
|
498
506
|
client._find_app_label("myapp")
|
|
499
507
|
|
|
500
508
|
# Only called once - second call uses cache
|
|
501
|
-
mock_glv.
|
|
509
|
+
mock_glv.assert_called_once()
|
|
502
510
|
|
|
503
511
|
def test_severity_label_cached(self) -> None:
|
|
504
512
|
client = LokiClient(base_url="http://localhost:3100")
|
|
@@ -508,7 +516,19 @@ class TestLabelDiscovery:
|
|
|
508
516
|
client._find_severity_label()
|
|
509
517
|
client._find_severity_label()
|
|
510
518
|
|
|
511
|
-
mock_glv.
|
|
519
|
+
mock_glv.assert_called_once()
|
|
520
|
+
|
|
521
|
+
def test_discovery_uses_30_day_range(self) -> None:
|
|
522
|
+
client = LokiClient(base_url="http://localhost:3100")
|
|
523
|
+
with patch.object(client, "get_label_values") as mock_glv:
|
|
524
|
+
mock_glv.return_value = ["myapp"]
|
|
525
|
+
client._find_app_label("myapp")
|
|
526
|
+
|
|
527
|
+
args = mock_glv.call_args
|
|
528
|
+
start = args.kwargs["start"]
|
|
529
|
+
end = args.kwargs["end"]
|
|
530
|
+
diff_days = (end - start) / (24 * 60 * 60 * 1_000_000_000)
|
|
531
|
+
assert diff_days == 30
|
|
512
532
|
|
|
513
533
|
|
|
514
534
|
class TestMergeStreams:
|
|
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.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/metric_sample.py
RENAMED
|
File without changes
|
{loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/metric_series.py
RENAMED
|
File without changes
|
{loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/query_result.py
RENAMED
|
File without changes
|
{loki_reader_core-0.2.1 → loki_reader_core-0.2.2}/src/loki_reader_core/models/query_stats.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|