elven-logs-interceptor-python 0.1.9__tar.gz → 0.1.10__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 (90) hide show
  1. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/PKG-INFO +6 -6
  2. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/pyproject.toml +11 -11
  3. elven_logs_interceptor_python-0.1.9/examples/basic_app.py +0 -18
  4. elven_logs_interceptor_python-0.1.9/examples/fastapi_integration.py +0 -26
  5. elven_logs_interceptor_python-0.1.9/examples/full_config_reference.py +0 -67
  6. elven_logs_interceptor_python-0.1.9/examples/high_volume.py +0 -30
  7. elven_logs_interceptor_python-0.1.9/examples/tracking_usage.py +0 -14
  8. elven_logs_interceptor_python-0.1.9/scripts/publish.sh +0 -180
  9. elven_logs_interceptor_python-0.1.9/test-apps/elven-live-demo/.env.example +0 -49
  10. elven_logs_interceptor_python-0.1.9/test-apps/elven-live-demo/README.md +0 -17
  11. elven_logs_interceptor_python-0.1.9/test-apps/elven-live-demo/app.py +0 -97
  12. elven_logs_interceptor_python-0.1.9/test-apps/elven-live-demo/run.sh +0 -21
  13. elven_logs_interceptor_python-0.1.9/test-apps/elven-observability-smoke/.env.example +0 -167
  14. elven_logs_interceptor_python-0.1.9/test-apps/elven-observability-smoke/README.md +0 -27
  15. elven_logs_interceptor_python-0.1.9/test-apps/elven-observability-smoke/app.py +0 -90
  16. elven_logs_interceptor_python-0.1.9/test-apps/elven-observability-smoke/run.sh +0 -21
  17. elven_logs_interceptor_python-0.1.9/tests/integration/test_api.py +0 -122
  18. elven_logs_interceptor_python-0.1.9/tests/unit/test_circuit_breaker_extra.py +0 -48
  19. elven_logs_interceptor_python-0.1.9/tests/unit/test_config_service.py +0 -144
  20. elven_logs_interceptor_python-0.1.9/tests/unit/test_core_components.py +0 -77
  21. elven_logs_interceptor_python-0.1.9/tests/unit/test_env_config.py +0 -59
  22. elven_logs_interceptor_python-0.1.9/tests/unit/test_integration_filters.py +0 -119
  23. elven_logs_interceptor_python-0.1.9/tests/unit/test_log_filter_extra.py +0 -68
  24. elven_logs_interceptor_python-0.1.9/tests/unit/test_log_service_unit.py +0 -578
  25. elven_logs_interceptor_python-0.1.9/tests/unit/test_loguru_sink.py +0 -137
  26. elven_logs_interceptor_python-0.1.9/tests/unit/test_loki_json_transport.py +0 -179
  27. elven_logs_interceptor_python-0.1.9/tests/unit/test_memory_buffer_extra.py +0 -145
  28. elven_logs_interceptor_python-0.1.9/tests/unit/test_protobuf_transport_safety.py +0 -141
  29. elven_logs_interceptor_python-0.1.9/tests/unit/test_resilient_transport.py +0 -211
  30. elven_logs_interceptor_python-0.1.9/tests/unit/test_runtime_interceptor.py +0 -88
  31. elven_logs_interceptor_python-0.1.9/tests/unit/test_utils_extra.py +0 -276
  32. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/.gitignore +0 -0
  33. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/ARCHITECTURE.md +0 -0
  34. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/README.md +0 -0
  35. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/__init__.py +0 -0
  36. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/application/__init__.py +0 -0
  37. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/application/config_service.py +0 -0
  38. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/application/log_service.py +0 -0
  39. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/config.py +0 -0
  40. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/domain/__init__.py +0 -0
  41. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/domain/entities.py +0 -0
  42. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/domain/interfaces.py +0 -0
  43. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/domain/value_objects.py +0 -0
  44. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/__init__.py +0 -0
  45. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/buffer/__init__.py +0 -0
  46. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/buffer/memory_buffer.py +0 -0
  47. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/circuit_breaker/__init__.py +0 -0
  48. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/circuit_breaker/circuit_breaker.py +0 -0
  49. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/compression/__init__.py +0 -0
  50. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/compression/base.py +0 -0
  51. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/compression/brotli_compressor.py +0 -0
  52. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/compression/factory.py +0 -0
  53. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/compression/gzip_compressor.py +0 -0
  54. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/compression/noop_compressor.py +0 -0
  55. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/context/__init__.py +0 -0
  56. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/context/context_provider.py +0 -0
  57. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/dlq/__init__.py +0 -0
  58. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/dlq/file_dlq.py +0 -0
  59. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/dlq/memory_dlq.py +0 -0
  60. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/filter/__init__.py +0 -0
  61. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/filter/log_filter.py +0 -0
  62. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/interceptors/__init__.py +0 -0
  63. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/interceptors/runtime_interceptor.py +0 -0
  64. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/internal_capture_guard.py +0 -0
  65. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/log_noise_filter.py +0 -0
  66. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/log_record_extra.py +0 -0
  67. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/memory/__init__.py +0 -0
  68. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/memory/memory_tracker.py +0 -0
  69. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/metrics/__init__.py +0 -0
  70. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/metrics/metrics_collector.py +0 -0
  71. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/transport/__init__.py +0 -0
  72. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/transport/loki_json_transport.py +0 -0
  73. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/transport/loki_protobuf_transport.py +0 -0
  74. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/transport/resilient_transport.py +0 -0
  75. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/transport/transport_factory.py +0 -0
  76. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/workers/__init__.py +0 -0
  77. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/infrastructure/workers/worker_pool.py +0 -0
  78. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/__init__.py +0 -0
  79. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/celery.py +0 -0
  80. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/django.py +0 -0
  81. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/fastapi.py +0 -0
  82. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/flask.py +0 -0
  83. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/logging_handler.py +0 -0
  84. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/loguru.py +0 -0
  85. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/integrations/structlog.py +0 -0
  86. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/preload.py +0 -0
  87. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/presentation/__init__.py +0 -0
  88. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/presentation/factory.py +0 -0
  89. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/types.py +0 -0
  90. {elven_logs_interceptor_python-0.1.9 → elven_logs_interceptor_python-0.1.10}/src/logs_interceptor/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elven-logs-interceptor-python
3
- Version: 0.1.9
3
+ Version: 0.1.10
4
4
  Summary: Production-grade logs interceptor for Python with Loki transport, resilience, batching, and framework integrations.
5
5
  Author: Elven Observability
6
6
  License: MIT
@@ -14,20 +14,20 @@ Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Topic :: System :: Logging
16
16
  Requires-Python: >=3.10
17
- Requires-Dist: httpx>=0.27.0
17
+ Requires-Dist: httpx<0.29.0,>=0.24.1
18
18
  Requires-Dist: typing-extensions>=4.12.0
19
19
  Provides-Extra: all
20
20
  Requires-Dist: brotli>=1.1.0; extra == 'all'
21
21
  Requires-Dist: celery>=5.4.0; extra == 'all'
22
22
  Requires-Dist: django>=4.2; extra == 'all'
23
- Requires-Dist: fastapi>=0.111.0; extra == 'all'
23
+ Requires-Dist: fastapi>=0.100.0; extra == 'all'
24
24
  Requires-Dist: flask>=3.0.0; extra == 'all'
25
25
  Requires-Dist: loguru>=0.7.2; extra == 'all'
26
26
  Requires-Dist: opentelemetry-api>=1.24.0; extra == 'all'
27
27
  Requires-Dist: orjson>=3.10.0; extra == 'all'
28
28
  Requires-Dist: protobuf>=5.0.0; extra == 'all'
29
29
  Requires-Dist: python-snappy>=0.7.1; extra == 'all'
30
- Requires-Dist: starlette>=0.37.0; extra == 'all'
30
+ Requires-Dist: starlette>=0.27.0; extra == 'all'
31
31
  Requires-Dist: structlog>=24.0.0; extra == 'all'
32
32
  Provides-Extra: celery
33
33
  Requires-Dist: celery>=5.4.0; extra == 'celery'
@@ -42,8 +42,8 @@ Requires-Dist: twine>=5.1.1; extra == 'dev'
42
42
  Provides-Extra: django
43
43
  Requires-Dist: django>=4.2; extra == 'django'
44
44
  Provides-Extra: fastapi
45
- Requires-Dist: fastapi>=0.111.0; extra == 'fastapi'
46
- Requires-Dist: starlette>=0.37.0; extra == 'fastapi'
45
+ Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
46
+ Requires-Dist: starlette>=0.27.0; extra == 'fastapi'
47
47
  Provides-Extra: flask
48
48
  Requires-Dist: flask>=3.0.0; extra == 'flask'
49
49
  Provides-Extra: loguru
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "elven-logs-interceptor-python"
7
- version = "0.1.9"
7
+ version = "0.1.10"
8
8
  description = "Production-grade logs interceptor for Python with Loki transport, resilience, batching, and framework integrations."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -32,7 +32,7 @@ classifiers = [
32
32
  "Topic :: System :: Logging",
33
33
  ]
34
34
  dependencies = [
35
- "httpx>=0.27.0",
35
+ "httpx>=0.24.1,<0.29.0",
36
36
  "typing-extensions>=4.12.0",
37
37
  ]
38
38
 
@@ -47,8 +47,8 @@ otel = [
47
47
  "opentelemetry-api>=1.24.0",
48
48
  ]
49
49
  fastapi = [
50
- "fastapi>=0.111.0",
51
- "starlette>=0.37.0",
50
+ "fastapi>=0.100.0",
51
+ "starlette>=0.27.0",
52
52
  ]
53
53
  django = [
54
54
  "django>=4.2",
@@ -71,8 +71,8 @@ all = [
71
71
  "python-snappy>=0.7.1",
72
72
  "brotli>=1.1.0",
73
73
  "opentelemetry-api>=1.24.0",
74
- "fastapi>=0.111.0",
75
- "starlette>=0.37.0",
74
+ "fastapi>=0.100.0",
75
+ "starlette>=0.27.0",
76
76
  "django>=4.2",
77
77
  "flask>=3.0.0",
78
78
  "celery>=5.4.0",
@@ -93,22 +93,22 @@ dev = [
93
93
  packages = ["src/logs_interceptor"]
94
94
 
95
95
  [tool.hatch.build.targets.sdist]
96
- include = [
96
+ only-include = [
97
97
  "/ARCHITECTURE.md",
98
98
  "/README.md",
99
- "/examples",
100
99
  "/pyproject.toml",
101
- "/scripts",
102
100
  "/src",
103
- "/test-apps",
104
- "/tests",
105
101
  ]
106
102
  exclude = [
103
+ "/.mypy_cache",
104
+ "/.pytest_cache",
105
+ "/.ruff_cache",
107
106
  "/.venv*",
108
107
  "/.logs-dlq",
109
108
  "/build",
110
109
  "/collector",
111
110
  "/dist",
111
+ "/test-apps",
112
112
  ]
113
113
 
114
114
  [tool.pytest.ini_options]
@@ -1,18 +0,0 @@
1
- from logs_interceptor import init
2
-
3
- init(
4
- {
5
- "appName": "my-service",
6
- "interceptConsole": True,
7
- "transport": {
8
- "url": "http://localhost:3100/loki/api/v1/push",
9
- "tenantId": "my-tenant",
10
- "compression": "gzip",
11
- "enableConnectionPooling": True,
12
- },
13
- "deadLetterQueue": {"enabled": True, "type": "file"},
14
- "circuitBreaker": {"enabled": True},
15
- }
16
- )
17
-
18
- print("service started")
@@ -1,26 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- from logs_interceptor import init, logger
4
- from logs_interceptor.integrations import FastAPIMiddleware
5
-
6
- init(
7
- {
8
- "transport": {
9
- "url": "http://localhost:3100/loki/api/v1/push",
10
- "tenantId": "my-tenant",
11
- "compression": "brotli",
12
- },
13
- "appName": "my-api",
14
- "interceptConsole": True,
15
- "deadLetterQueue": {"enabled": True, "type": "file"},
16
- }
17
- )
18
-
19
- app = FastAPI()
20
- app.add_middleware(FastAPIMiddleware, logger=logger)
21
-
22
-
23
- @app.get("/ping")
24
- def ping() -> dict[str, str]:
25
- logger.info("ping called")
26
- return {"message": "pong"}
@@ -1,67 +0,0 @@
1
- from logs_interceptor import init
2
-
3
- init(
4
- {
5
- "appName": "my-service-name",
6
- "version": "1.2.0",
7
- "environment": "production",
8
- "interceptConsole": True,
9
- "preserveOriginalConsole": True,
10
- "silentErrors": False,
11
- "debug": False,
12
- "labels": {"region": "us-east-1", "tier": "gold"},
13
- "dynamicLabels": {
14
- "pod_id": lambda: "unknown",
15
- },
16
- "transport": {
17
- "url": "http://localhost:3100/loki/api/v1/push",
18
- "tenantId": "my-tenant-id",
19
- "timeout": 10000,
20
- "maxRetries": 3,
21
- "retryDelay": 1000,
22
- "enableConnectionPooling": True,
23
- "maxSockets": 50,
24
- "compression": "snappy",
25
- "compressionLevel": 6,
26
- "compressionThreshold": 1024,
27
- "useWorkers": True,
28
- "maxWorkers": 2,
29
- "workerTimeout": 30000,
30
- },
31
- "buffer": {
32
- "maxSize": 1000,
33
- "flushInterval": 5000,
34
- "maxMemoryMB": 50,
35
- "maxAge": 30000,
36
- "autoFlush": True,
37
- },
38
- "filter": {
39
- "levels": ["info", "warn", "error", "fatal"],
40
- "patterns": ["health/check"],
41
- "samplingRate": 1.0,
42
- "sanitize": True,
43
- "sensitivePatterns": ["password", "token", "secret"],
44
- "maxMessageLength": 8192,
45
- },
46
- "circuitBreaker": {
47
- "enabled": True,
48
- "failureThreshold": 20,
49
- "resetTimeout": 30000,
50
- "halfOpenRequests": 3,
51
- },
52
- "deadLetterQueue": {
53
- "enabled": True,
54
- "type": "file",
55
- "basePath": "./.logs-dlq",
56
- "maxSize": 1000,
57
- "maxRetries": 10,
58
- },
59
- "performance": {
60
- "useWorkers": True,
61
- "maxConcurrentFlushes": 5,
62
- "workerTimeout": 30000,
63
- },
64
- "enableMetrics": True,
65
- "enableHealthCheck": True,
66
- }
67
- )
@@ -1,30 +0,0 @@
1
- from logs_interceptor import init, logger
2
-
3
- init(
4
- {
5
- "appName": "high-volume-service",
6
- "interceptConsole": True,
7
- "transport": {
8
- "url": "http://localhost:3100/loki/api/v1/push",
9
- "tenantId": "production",
10
- "compression": "snappy",
11
- "maxSockets": 100,
12
- "timeout": 10000,
13
- "useWorkers": True,
14
- "maxWorkers": 4,
15
- "compressionThreshold": 4096,
16
- "compressionLevel": 6,
17
- },
18
- "buffer": {
19
- "maxSize": 2000,
20
- "flushInterval": 2000,
21
- "maxMemoryMB": 512,
22
- },
23
- "performance": {
24
- "maxConcurrentFlushes": 10,
25
- },
26
- }
27
- )
28
-
29
- for i in range(10000):
30
- logger.info("High volume event", {"index": i})
@@ -1,14 +0,0 @@
1
- from logs_interceptor import init, logger
2
-
3
- init(
4
- {
5
- "appName": "analytics-service",
6
- "transport": {
7
- "url": "http://localhost:3100/loki/api/v1/push",
8
- "tenantId": "analytics",
9
- },
10
- }
11
- )
12
-
13
- logger.track_event("user_signup", {"user_id": "u_123", "plan": "pro"})
14
- logger.track_event("api_request", {"endpoint": "/users", "status_code": 200})
@@ -1,180 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -Eeuo pipefail
3
-
4
- ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
- cd "${ROOT_DIR}"
6
-
7
- PYTHON_BIN="${PYTHON_BIN:-python3}"
8
- REPOSITORY="testpypi"
9
- TOKEN_ENV=""
10
- SKIP_CHECKS=0
11
- SKIP_BUILD=0
12
- DRY_RUN=0
13
- SKIP_EXISTING=1
14
-
15
- TEST_PYPI_URL="https://test.pypi.org/legacy/"
16
- PYPI_URL="https://upload.pypi.org/legacy/"
17
-
18
- usage() {
19
- cat <<'EOF'
20
- Usage:
21
- ./scripts/publish.sh [options]
22
-
23
- Options:
24
- --repository {testpypi|pypi} Publish target (default: testpypi)
25
- --token-env NAME Env var with API token
26
- --skip-checks Skip ruff + mypy + pytest
27
- --skip-build Skip build and twine check steps
28
- --no-skip-existing Do not pass --skip-existing to twine upload
29
- --dry-run Run validations/build but do not upload
30
- -h, --help Show this message
31
-
32
- Env:
33
- PYTHON_BIN Python executable (default: python3)
34
- TEST_PYPI_API_TOKEN Default token env for --repository testpypi
35
- PYPI_API_TOKEN Default token env for --repository pypi
36
- EOF
37
- }
38
-
39
- require_python_module() {
40
- local module_name="$1"
41
- if ! "${PYTHON_BIN}" -c "import ${module_name}" >/dev/null 2>&1; then
42
- echo "Missing Python module: ${module_name}" >&2
43
- echo "Install dependencies with: ${PYTHON_BIN} -m pip install -e \".[dev]\"" >&2
44
- exit 1
45
- fi
46
- }
47
-
48
- run_checks() {
49
- echo "[publish] running quality gates..."
50
- "${PYTHON_BIN}" -m ruff check .
51
- "${PYTHON_BIN}" -m mypy src
52
- "${PYTHON_BIN}" -m pytest -q
53
- }
54
-
55
- clean_artifacts() {
56
- rm -rf build dist
57
- find . -maxdepth 1 -type d -name "*.egg-info" -exec rm -rf {} +
58
- }
59
-
60
- build_artifacts() {
61
- echo "[publish] building distribution artifacts..."
62
- clean_artifacts
63
- "${PYTHON_BIN}" -m build
64
- "${PYTHON_BIN}" -m twine check dist/*
65
- }
66
-
67
- resolve_repository_url() {
68
- if [[ "${REPOSITORY}" == "testpypi" ]]; then
69
- echo "${TEST_PYPI_URL}"
70
- return
71
- fi
72
- echo "${PYPI_URL}"
73
- }
74
-
75
- resolve_token_env() {
76
- if [[ -n "${TOKEN_ENV}" ]]; then
77
- echo "${TOKEN_ENV}"
78
- return
79
- fi
80
- if [[ "${REPOSITORY}" == "testpypi" ]]; then
81
- echo "TEST_PYPI_API_TOKEN"
82
- return
83
- fi
84
- echo "PYPI_API_TOKEN"
85
- }
86
-
87
- while [[ $# -gt 0 ]]; do
88
- case "$1" in
89
- --repository)
90
- REPOSITORY="$2"
91
- shift 2
92
- ;;
93
- --token-env)
94
- TOKEN_ENV="$2"
95
- shift 2
96
- ;;
97
- --skip-checks)
98
- SKIP_CHECKS=1
99
- shift
100
- ;;
101
- --skip-build)
102
- SKIP_BUILD=1
103
- shift
104
- ;;
105
- --no-skip-existing)
106
- SKIP_EXISTING=0
107
- shift
108
- ;;
109
- --dry-run)
110
- DRY_RUN=1
111
- shift
112
- ;;
113
- -h|--help)
114
- usage
115
- exit 0
116
- ;;
117
- *)
118
- echo "Unknown option: $1" >&2
119
- usage
120
- exit 1
121
- ;;
122
- esac
123
- done
124
-
125
- if [[ "${REPOSITORY}" != "testpypi" && "${REPOSITORY}" != "pypi" ]]; then
126
- echo "Invalid --repository value: ${REPOSITORY}" >&2
127
- exit 1
128
- fi
129
-
130
- if [[ "${SKIP_CHECKS}" -eq 0 ]]; then
131
- require_python_module "ruff"
132
- require_python_module "mypy"
133
- require_python_module "pytest"
134
- fi
135
-
136
- if [[ "${SKIP_BUILD}" -eq 0 ]]; then
137
- require_python_module "build"
138
- require_python_module "twine"
139
- elif [[ "${DRY_RUN}" -eq 0 ]]; then
140
- require_python_module "twine"
141
- fi
142
-
143
- if [[ "${SKIP_CHECKS}" -eq 0 ]]; then
144
- run_checks
145
- fi
146
-
147
- if [[ "${SKIP_BUILD}" -eq 0 ]]; then
148
- build_artifacts
149
- fi
150
-
151
- if [[ "${DRY_RUN}" -eq 1 ]]; then
152
- echo "[publish] dry-run enabled, upload skipped."
153
- echo "[publish] built files:"
154
- ls -1 dist/* 2>/dev/null || true
155
- exit 0
156
- fi
157
-
158
- repository_url="$(resolve_repository_url)"
159
- token_env_name="$(resolve_token_env)"
160
- token_value="${!token_env_name-}"
161
-
162
- if [[ -z "${token_value}" ]]; then
163
- echo "Missing publish token in env var: ${token_env_name}" >&2
164
- exit 1
165
- fi
166
-
167
- twine_args=(
168
- upload
169
- --repository-url "${repository_url}"
170
- --non-interactive
171
- )
172
- if [[ "${SKIP_EXISTING}" -eq 1 ]]; then
173
- twine_args+=(--skip-existing)
174
- fi
175
- twine_args+=(dist/*)
176
-
177
- echo "[publish] uploading to ${REPOSITORY} (${repository_url})..."
178
- TWINE_USERNAME="__token__" TWINE_PASSWORD="${token_value}" "${PYTHON_BIN}" -m twine "${twine_args[@]}"
179
-
180
- echo "[publish] done."
@@ -1,49 +0,0 @@
1
- LOGS_URL=https://loki.elvenobservability.com/loki/api/v1/push
2
- LOGS_TENANT=elven
3
- LOGS_TOKEN=replace-with-your-token
4
- LOGS_APP_NAME=elven-live-demo
5
- LOGS_APP_VERSION=1.0.0
6
- LOGS_ENVIRONMENT=local
7
-
8
- LOGS_COMPRESSION=gzip
9
- LOGS_COMPRESSION_LEVEL=4
10
- LOGS_COMPRESSION_THRESHOLD=1024
11
- LOGS_CONNECTION_POOLING=true
12
- LOGS_MAX_SOCKETS=50
13
- LOGS_TIMEOUT=10000
14
- LOGS_MAX_RETRIES=3
15
- LOGS_RETRY_DELAY=1000
16
-
17
- LOGS_BUFFER_MAX_SIZE=25
18
- LOGS_BUFFER_FLUSH_INTERVAL=1500
19
- LOGS_BUFFER_MAX_MEMORY_MB=128
20
- LOGS_BUFFER_MAX_AGE=30000
21
- LOGS_BUFFER_AUTO_FLUSH=true
22
-
23
- LOGS_FILTER_LEVELS=debug,info,warn,error,fatal
24
- LOGS_FILTER_SAMPLING_RATE=1.0
25
- LOGS_FILTER_SANITIZE=true
26
- LOGS_FILTER_MAX_MESSAGE_LENGTH=8192
27
-
28
- LOGS_CIRCUIT_BREAKER_ENABLED=true
29
- LOGS_CIRCUIT_BREAKER_FAILURE_THRESHOLD=20
30
- LOGS_CIRCUIT_BREAKER_RESET_TIMEOUT=15000
31
- LOGS_CIRCUIT_BREAKER_HALF_OPEN_REQUESTS=3
32
-
33
- LOGS_DLQ_ENABLED=true
34
- LOGS_DLQ_TYPE=file
35
- LOGS_DLQ_MAX_SIZE=1000
36
- LOGS_DLQ_MAX_RETRIES=3
37
- LOGS_DLQ_BASE_PATH=./.logs-dlq
38
-
39
- LOGS_MAX_CONCURRENT_FLUSHES=5
40
- LOGS_INTERCEPT_CONSOLE=true
41
- LOGS_PRESERVE_ORIGINAL_CONSOLE=true
42
- LOGS_ENABLE_METRICS=true
43
- LOGS_ENABLE_HEALTH_CHECK=true
44
- LOGS_DEBUG=false
45
- LOGS_SILENT_ERRORS=false
46
- LOGS_ENABLED=true
47
-
48
- LOGS_LABEL_SERVICE=elven-live-demo
49
- LOGS_LABEL_ENVIRONMENT=local
@@ -1,17 +0,0 @@
1
- # Elven Live Demo
2
-
3
- Local Python app to exercise `elven-logs-interceptor-python` against the Elven Loki endpoint.
4
-
5
- ## Run
6
-
7
- ```bash
8
- cd /Users/leonardozwirtes/Documents/Projects/logs-interceptor-python
9
- chmod +x test-apps/elven-live-demo/run.sh
10
- ./test-apps/elven-live-demo/run.sh
11
- ```
12
-
13
- ## Notes
14
-
15
- - The tracked config template is `.env.example`.
16
- - The real token lives only in local `.env`, which is ignored by Git.
17
- - The package import remains `logs_interceptor`.
@@ -1,97 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import random
5
- import time
6
-
7
- from logs_interceptor import destroy, init, logger
8
-
9
-
10
- def emit_startup_logs() -> None:
11
- logger.info("demo app started", {"component": "startup"})
12
- logger.track_event("demo_started", {"source": "local-run", "at": time.time()})
13
-
14
-
15
- def emit_business_logs() -> None:
16
- for idx in range(10):
17
- logger.info(
18
- "processing item",
19
- {
20
- "idx": idx,
21
- "value": random.randint(100, 999),
22
- "duration_ms": round(random.uniform(5, 30), 2),
23
- },
24
- )
25
-
26
- logger.warn("slow dependency detected", {"dependency": "inventory-service", "latency_ms": 187})
27
-
28
- try:
29
- raise RuntimeError("simulated business exception")
30
- except RuntimeError as exc:
31
- logger.error(
32
- "handled domain error",
33
- {
34
- "error": str(exc),
35
- "kind": "business",
36
- },
37
- )
38
-
39
-
40
- def emit_sync_context_logs() -> None:
41
- def _run() -> None:
42
- logger.info("sync request started", {"method": "GET", "path": "/products"})
43
- print("plain print still works and is intercepted")
44
-
45
- logger.with_context(
46
- {
47
- "request_id": "demo-sync-request-1",
48
- "trace_id": "demo-sync-trace-1",
49
- "span_id": "demo-sync-span-1",
50
- },
51
- _run,
52
- )
53
-
54
-
55
- async def emit_async_context_logs() -> None:
56
- async def _run() -> None:
57
- logger.info("async job started", {"job": "catalog-refresh"})
58
- await asyncio.sleep(0.05)
59
- logger.track_event("catalog_refresh_finished", {"ok": True})
60
-
61
- await logger.with_context_async(
62
- {
63
- "request_id": "demo-async-request-1",
64
- "trace_id": "demo-async-trace-1",
65
- "span_id": "demo-async-span-1",
66
- },
67
- _run,
68
- )
69
-
70
-
71
- def print_runtime_summary() -> None:
72
- metrics = logger.get_metrics()
73
- health = logger.get_health()
74
- print(
75
- {
76
- "processed": metrics.get("logs_processed"),
77
- "dropped": metrics.get("logs_dropped"),
78
- "flush_count": metrics.get("flush_count"),
79
- "error_count": metrics.get("error_count"),
80
- }
81
- )
82
- print({"health": health})
83
-
84
-
85
- def main() -> None:
86
- init()
87
- emit_startup_logs()
88
- emit_business_logs()
89
- emit_sync_context_logs()
90
- asyncio.run(emit_async_context_logs())
91
- logger.flush()
92
- print_runtime_summary()
93
- destroy()
94
-
95
-
96
- if __name__ == "__main__":
97
- main()
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -Eeuo pipefail
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- ROOT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
6
-
7
- if [[ ! -f "${SCRIPT_DIR}/.env" ]]; then
8
- echo "Missing .env at ${SCRIPT_DIR}/.env" >&2
9
- if [[ -f "${SCRIPT_DIR}/.env.example" ]]; then
10
- echo "Create it with: cp ${SCRIPT_DIR}/.env.example ${SCRIPT_DIR}/.env" >&2
11
- fi
12
- exit 1
13
- fi
14
-
15
- set -a
16
- source "${SCRIPT_DIR}/.env"
17
- set +a
18
-
19
- export PYTHONPATH="${ROOT_DIR}/src:${PYTHONPATH:-}"
20
-
21
- python3 "${SCRIPT_DIR}/app.py"