devlogs 2.3.4__tar.gz → 2.3.5__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.
- {devlogs-2.3.4/src/devlogs.egg-info → devlogs-2.3.5}/PKG-INFO +1 -1
- {devlogs-2.3.4 → devlogs-2.3.5}/pyproject.toml +1 -1
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/_version_static.py +1 -1
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/cli.py +14 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/config.py +10 -2
- {devlogs-2.3.4 → devlogs-2.3.5/src/devlogs.egg-info}/PKG-INFO +1 -1
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_cli.py +22 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/LICENSE +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/MANIFEST.in +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/README.md +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/setup.cfg +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/__main__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/build_info.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/auth.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/cli.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/errors.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/forwarder.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/ingestor.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/loki_plugin.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/plugins.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/schema.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/collector/server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/context.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/demo.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/devlogs_client.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/formatting.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/handler.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/jenkins/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/jenkins/cli.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/jenkins/core.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/levels.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/loki/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/loki/queries.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/mcp/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/mcp/server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/opensearch/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/opensearch/client.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/opensearch/indexing.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/opensearch/mappings.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/opensearch/queries.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/proxy/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/proxy/server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/retention.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/scrub.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/time_utils.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/version.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/web/__init__.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/web/server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/web/static/devlogs.css +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/web/static/devlogs.js +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/web/static/index.html +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs/wrapper.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs.egg-info/SOURCES.txt +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs.egg-info/dependency_links.txt +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs.egg-info/entry_points.txt +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs.egg-info/requires.txt +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/src/devlogs.egg-info/top_level.txt +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_build_info.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_collector_auth.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_collector_config.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_collector_plugins.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_collector_schema.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_collector_server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_config.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_context.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_devlogs_client.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_formatting.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_handler.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_indexing.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_levels.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_mappings.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_mcp_server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_opensearch_client.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_opensearch_queries.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_proxy_server.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_retention.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_scrub.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_time_utils.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_url_parsing.py +0 -0
- {devlogs-2.3.4 → devlogs-2.3.5}/tests/test_web.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# AUTO-GENERATED at build time — do not edit or commit
|
|
2
|
-
__version__ = "2.3.
|
|
2
|
+
__version__ = "2.3.5"
|
|
@@ -926,6 +926,13 @@ def tail(
|
|
|
926
926
|
_apply_common_options(env, url)
|
|
927
927
|
|
|
928
928
|
cfg = load_config()
|
|
929
|
+
if cfg.url_mode == "collector":
|
|
930
|
+
typer.echo(typer.style(
|
|
931
|
+
"Error: the provided URL is a collector (ingest) endpoint and cannot be used for querying.\n"
|
|
932
|
+
"For Loki backends, use lokis://TOKEN@host/path instead of https://TOKEN@host/path",
|
|
933
|
+
fg=typer.colors.RED
|
|
934
|
+
), err=True)
|
|
935
|
+
raise typer.Exit(1)
|
|
929
936
|
if cfg.is_loki:
|
|
930
937
|
_tail_loki(cfg, application=application, operation_id=operation_id, area=area,
|
|
931
938
|
component=component, level=level, since=since, limit=limit, follow=follow,
|
|
@@ -1115,6 +1122,13 @@ def search(
|
|
|
1115
1122
|
_apply_common_options(env, url)
|
|
1116
1123
|
|
|
1117
1124
|
cfg = load_config()
|
|
1125
|
+
if cfg.url_mode == "collector":
|
|
1126
|
+
typer.echo(typer.style(
|
|
1127
|
+
"Error: the provided URL is a collector (ingest) endpoint and cannot be used for querying.\n"
|
|
1128
|
+
"For Loki backends, use lokis://TOKEN@host/path instead of https://TOKEN@host/path",
|
|
1129
|
+
fg=typer.colors.RED
|
|
1130
|
+
), err=True)
|
|
1131
|
+
raise typer.Exit(1)
|
|
1118
1132
|
if cfg.is_loki:
|
|
1119
1133
|
_search_loki(cfg, q=q, application=application, area=area,
|
|
1120
1134
|
component=component, level=level, operation_id=operation_id,
|
|
@@ -414,8 +414,9 @@ class DevlogsConfig:
|
|
|
414
414
|
# Treat unparseable DEVLOGS_URL as legacy OpenSearch
|
|
415
415
|
opensearch_url_config = _parse_opensearch_url(devlogs_url)
|
|
416
416
|
|
|
417
|
-
# Legacy: DEVLOGS_OPENSEARCH_URL overrides OpenSearch settings from DEVLOGS_URL
|
|
418
|
-
|
|
417
|
+
# Legacy: DEVLOGS_OPENSEARCH_URL overrides OpenSearch settings from DEVLOGS_URL,
|
|
418
|
+
# but NOT when the URL was explicitly set via --url flag.
|
|
419
|
+
if legacy_opensearch_url and not _url_set_explicitly:
|
|
419
420
|
opensearch_url_config = _parse_opensearch_url(legacy_opensearch_url)
|
|
420
421
|
# Parse application filter from opensearch:// URL (second path segment)
|
|
421
422
|
if legacy_opensearch_url.startswith("opensearchs://") or legacy_opensearch_url.startswith("opensearch://"):
|
|
@@ -539,15 +540,22 @@ def set_dotenv_path(path: str):
|
|
|
539
540
|
_dotenv_loaded = False # Reset to force reload with new path
|
|
540
541
|
|
|
541
542
|
|
|
543
|
+
_url_set_explicitly = False
|
|
544
|
+
|
|
542
545
|
def set_url(url: str):
|
|
543
546
|
"""Set the URL, auto-detecting whether it's a collector or OpenSearch URL.
|
|
544
547
|
|
|
545
548
|
Uses parse_url() to detect the URL type:
|
|
546
549
|
- Collector URLs → sets DEVLOGS_URL
|
|
547
550
|
- OpenSearch URLs → sets DEVLOGS_OPENSEARCH_URL
|
|
551
|
+
|
|
552
|
+
When called (i.e. via --url flag), marks the URL as explicitly set so that
|
|
553
|
+
dotenv values cannot silently override it.
|
|
548
554
|
"""
|
|
555
|
+
global _url_set_explicitly
|
|
549
556
|
if not url:
|
|
550
557
|
return
|
|
558
|
+
_url_set_explicitly = True
|
|
551
559
|
try:
|
|
552
560
|
parsed = parse_url(url)
|
|
553
561
|
except URLParseError:
|
|
@@ -919,3 +919,25 @@ class TestLokiCLI:
|
|
|
919
919
|
result = runner.invoke(cli.app, ["--url", "lokis://token@host.example.io/query", "last-error"])
|
|
920
920
|
assert result.exit_code == 1
|
|
921
921
|
assert "--application is required" in result.output
|
|
922
|
+
|
|
923
|
+
def test_tail_rejects_collector_url(self, monkeypatch):
|
|
924
|
+
"""Test that tail fails with a clear error for collector (https) URLs."""
|
|
925
|
+
monkeypatch.setattr(config, "_dotenv_loaded", True)
|
|
926
|
+
monkeypatch.delenv("DEVLOGS_OPENSEARCH_URL", raising=False)
|
|
927
|
+
monkeypatch.delenv("DEVLOGS_OPENSEARCH_HOST", raising=False)
|
|
928
|
+
runner = CliRunner()
|
|
929
|
+
result = runner.invoke(cli.app, ["--url", "https://token@host.example.io/ingest", "tail"])
|
|
930
|
+
assert result.exit_code == 1
|
|
931
|
+
assert "collector" in result.output
|
|
932
|
+
assert "lokis://" in result.output
|
|
933
|
+
|
|
934
|
+
def test_search_rejects_collector_url(self, monkeypatch):
|
|
935
|
+
"""Test that search fails with a clear error for collector (https) URLs."""
|
|
936
|
+
monkeypatch.setattr(config, "_dotenv_loaded", True)
|
|
937
|
+
monkeypatch.delenv("DEVLOGS_OPENSEARCH_URL", raising=False)
|
|
938
|
+
monkeypatch.delenv("DEVLOGS_OPENSEARCH_HOST", raising=False)
|
|
939
|
+
runner = CliRunner()
|
|
940
|
+
result = runner.invoke(cli.app, ["--url", "https://token@host.example.io/ingest", "search"])
|
|
941
|
+
assert result.exit_code == 1
|
|
942
|
+
assert "collector" in result.output
|
|
943
|
+
assert "lokis://" in result.output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|