loki-reader-core 0.2.2__tar.gz → 0.2.3__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.
Files changed (21) hide show
  1. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/PKG-INFO +1 -1
  2. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/pyproject.toml +1 -1
  3. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/__init__.py +1 -1
  4. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/client.py +23 -15
  5. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/tests/test_client.py +5 -25
  6. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/.gitignore +0 -0
  7. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/README.md +0 -0
  8. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/build-publish.sh +0 -0
  9. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/dev-requirements.txt +0 -0
  10. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/exceptions.py +0 -0
  11. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/__init__.py +0 -0
  12. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/log_entry.py +0 -0
  13. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/log_stream.py +0 -0
  14. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/metric_sample.py +0 -0
  15. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/metric_series.py +0 -0
  16. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/query_result.py +0 -0
  17. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/models/query_stats.py +0 -0
  18. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/src/loki_reader_core/utils.py +0 -0
  19. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/tests/__init__.py +0 -0
  20. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/tests/test_models.py +0 -0
  21. {loki_reader_core-0.2.2 → loki_reader_core-0.2.3}/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.2
3
+ Version: 0.2.3
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "loki-reader-core"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  authors = [
5
5
  { name="Jason Byteforge", email="jason@mzmail.me" },
6
6
  ]
@@ -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.2"
9
+ __version__ = "0.2.3"
10
10
 
11
11
  __all__ = [
12
12
  "LokiClient",
@@ -301,9 +301,8 @@ class LokiClient:
301
301
  if app_value in self._app_label_cache:
302
302
  return self._app_label_cache[app_value]
303
303
 
304
- start, end = self._discovery_time_range()
305
304
  for label_name in APP_LABEL_NAMES:
306
- values = self.get_label_values(label_name, start=start, end=end)
305
+ values = self.get_label_values(label_name)
307
306
  if app_value in values:
308
307
  self._app_label_cache[app_value] = label_name
309
308
  return label_name
@@ -325,9 +324,8 @@ class LokiClient:
325
324
  if self._severity_label_cache is not None:
326
325
  return self._severity_label_cache
327
326
 
328
- start, end = self._discovery_time_range()
329
327
  for label_name in SEVERITY_LABEL_NAMES:
330
- values = self.get_label_values(label_name, start=start, end=end)
328
+ values = self.get_label_values(label_name)
331
329
  if values:
332
330
  self._severity_label_cache = label_name
333
331
  return label_name
@@ -452,6 +450,10 @@ class LokiClient:
452
450
  """
453
451
  Get list of available label names.
454
452
 
453
+ Defaults to a 30-day lookback when no time range is provided,
454
+ since Loki's label API may only return labels for recently
455
+ active streams without an explicit range.
456
+
455
457
  Args:
456
458
  start: Optional start timestamp in nanoseconds.
457
459
  end: Optional end timestamp in nanoseconds.
@@ -459,14 +461,15 @@ class LokiClient:
459
461
  Returns:
460
462
  List of label names.
461
463
  """
462
- params = {}
464
+ if start is None and end is None:
465
+ start, end = self._discovery_time_range()
463
466
 
464
- if start is not None:
465
- params["start"] = str(start)
466
- if end is not None:
467
- params["end"] = str(end)
467
+ params = {
468
+ "start": str(start),
469
+ "end": str(end),
470
+ }
468
471
 
469
- response = self._request("GET", "/loki/api/v1/labels", params or None)
472
+ response = self._request("GET", "/loki/api/v1/labels", params)
470
473
  return response.get("data", [])
471
474
 
472
475
  def get_label_values(
@@ -478,6 +481,10 @@ class LokiClient:
478
481
  """
479
482
  Get list of values for a specific label.
480
483
 
484
+ Defaults to a 30-day lookback when no time range is provided,
485
+ since Loki's label API may only return values for recently
486
+ active streams without an explicit range.
487
+
481
488
  Args:
482
489
  label: Label name to get values for.
483
490
  start: Optional start timestamp in nanoseconds.
@@ -486,12 +493,13 @@ class LokiClient:
486
493
  Returns:
487
494
  List of label values.
488
495
  """
489
- params = {}
496
+ if start is None and end is None:
497
+ start, end = self._discovery_time_range()
490
498
 
491
- if start is not None:
492
- params["start"] = str(start)
493
- if end is not None:
494
- params["end"] = str(end)
499
+ params = {
500
+ "start": str(start),
501
+ "end": str(end),
502
+ }
495
503
 
496
504
  endpoint = f"/loki/api/v1/label/{label}/values"
497
505
  response = self._request("GET", endpoint, params or None)
@@ -453,16 +453,12 @@ 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.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
456
+ mock_glv.assert_called_once_with("application")
461
457
 
462
458
  def test_find_app_label_job(self) -> None:
463
459
  client = LokiClient(base_url="http://localhost:3100")
464
460
  with patch.object(client, "get_label_values") as mock_glv:
465
- def side_effect(label: str, start: int = None, end: int = None) -> list[str]:
461
+ def side_effect(label: str) -> list[str]:
466
462
  if label == "job":
467
463
  return ["myapp", "worker"]
468
464
  return []
@@ -484,11 +480,7 @@ class TestLabelDiscovery:
484
480
  mock_glv.return_value = ["info", "error", "warn"]
485
481
  result = client._find_severity_label()
486
482
  assert result == "level"
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
483
+ mock_glv.assert_called_once_with("level")
492
484
 
493
485
  def test_find_severity_label_none(self) -> None:
494
486
  client = LokiClient(base_url="http://localhost:3100")
@@ -506,7 +498,7 @@ class TestLabelDiscovery:
506
498
  client._find_app_label("myapp")
507
499
 
508
500
  # Only called once - second call uses cache
509
- mock_glv.assert_called_once()
501
+ mock_glv.assert_called_once_with("application")
510
502
 
511
503
  def test_severity_label_cached(self) -> None:
512
504
  client = LokiClient(base_url="http://localhost:3100")
@@ -516,19 +508,7 @@ class TestLabelDiscovery:
516
508
  client._find_severity_label()
517
509
  client._find_severity_label()
518
510
 
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
511
+ mock_glv.assert_called_once_with("level")
532
512
 
533
513
 
534
514
  class TestMergeStreams: