structlog-config 0.5.0__tar.gz → 0.6.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: structlog-config
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: A comprehensive structlog configuration with sensible defaults for development and production environments, featuring context management, exception formatting, and path prettification.
5
5
  Keywords: logging,structlog,json-logging,structured-logging
6
6
  Author: Michael Bianco
@@ -9,8 +9,10 @@ Requires-Dist: orjson>=3.10.15
9
9
  Requires-Dist: python-decouple-typed>=3.11.0
10
10
  Requires-Dist: python-ipware>=3.0.0
11
11
  Requires-Dist: structlog>=25.2.0
12
- Requires-Python: >=3.10
12
+ Requires-Dist: fastapi-ipware>=0.1.0 ; extra == 'fastapi'
13
+ Requires-Python: >=3.11
13
14
  Project-URL: Repository, https://github.com/iloveitaly/structlog-config
15
+ Provides-Extra: fastapi
14
16
  Description-Content-Type: text/markdown
15
17
 
16
18
  # Opinionated Defaults for Structlog
@@ -29,6 +31,18 @@ Here are the main goals:
29
31
  * Ability to log level and output (i.e. file path) *by logger* for easy development debugging
30
32
  * If you are using fastapi, structured logging for access logs
31
33
 
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install structlog-config
38
+ ```
39
+
40
+ Or with [uv](https://docs.astral.sh/uv/):
41
+
42
+ ```bash
43
+ uv add structlog-config
44
+ ```
45
+
32
46
  ## Usage
33
47
 
34
48
  ```python
@@ -108,6 +122,8 @@ For example, if you wanted to [mimic `OPENAI_LOG` functionality](https://github.
108
122
 
109
123
  ## FastAPI Access Logger
110
124
 
125
+ **Note:** Requires `pip install structlog-config[fastapi]` for FastAPI dependencies.
126
+
111
127
  Structured, simple access log with request timing to replace the default fastapi access log. Why?
112
128
 
113
129
  1. It's less verbose
@@ -119,6 +135,64 @@ Here's how to use it:
119
135
  1. [Disable fastapi's default logging.](https://github.com/iloveitaly/python-starter-template/blob/f54cb47d8d104987f2e4a668f9045a62e0d6818a/main.py#L55-L56)
120
136
  2. [Add the middleware to your FastAPI app.](https://github.com/iloveitaly/python-starter-template/blob/f54cb47d8d104987f2e4a668f9045a62e0d6818a/app/routes/middleware/__init__.py#L63-L65)
121
137
 
138
+ ## Pytest Plugin: Capture Logs on Failure
139
+
140
+ A pytest plugin that captures logs per-test and displays them only when tests fail. This keeps your test output clean while ensuring you have all the debugging information you need when something goes wrong.
141
+
142
+ ### Features
143
+
144
+ - Only shows logs for failing tests (keeps output clean)
145
+ - Captures logs from all test phases (setup, call, teardown)
146
+ - Unique log file per test
147
+ - Optional persistent log storage for debugging
148
+ - Automatically handles `PYTHON_LOG_PATH` environment variable
149
+
150
+ ### Usage
151
+
152
+ Enable the plugin with the `--capture-logs-on-fail` flag:
153
+
154
+ ```bash
155
+ pytest --capture-logs-on-fail
156
+ ```
157
+
158
+ Or enable it permanently in `pytest.ini` or `pyproject.toml`:
159
+
160
+ ```toml
161
+ [tool.pytest.ini_options]
162
+ addopts = ["--capture-logs-on-fail"]
163
+ ```
164
+
165
+ ### Persist Logs to Directory
166
+
167
+ To keep all test logs for later inspection (useful for CI/CD debugging):
168
+
169
+ ```bash
170
+ pytest --capture-logs-dir=./test-logs
171
+ ```
172
+
173
+ This creates a log file for each test and disables automatic cleanup.
174
+
175
+ ### How It Works
176
+
177
+ 1. Sets `PYTHON_LOG_PATH` environment variable to a unique temp file for each test
178
+ 2. Your application logs (via `configure_logger()`) write to this file
179
+ 3. On test failure, the plugin prints the captured logs to stdout
180
+ 4. Log files are cleaned up after the test session (unless `--capture-logs-dir` is used)
181
+
182
+ ### Example Output
183
+
184
+ When a test fails, you'll see:
185
+
186
+ ```
187
+ FAILED tests/test_user.py::test_user_login
188
+
189
+ --- Captured logs for failed test (call): tests/test_user.py::test_user_login ---
190
+ 2025-11-01 18:30:00 [info] User login started user_id=123
191
+ 2025-11-01 18:30:01 [error] Database connection failed timeout=5.0
192
+ ```
193
+
194
+ For passing tests, no log output is shown, keeping your test output clean and focused.
195
+
122
196
  ## iPython
123
197
 
124
198
  Often it's helpful to update logging level within an iPython session. You can do this and make sure all loggers pick up on it.
@@ -14,6 +14,18 @@ Here are the main goals:
14
14
  * Ability to log level and output (i.e. file path) *by logger* for easy development debugging
15
15
  * If you are using fastapi, structured logging for access logs
16
16
 
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install structlog-config
21
+ ```
22
+
23
+ Or with [uv](https://docs.astral.sh/uv/):
24
+
25
+ ```bash
26
+ uv add structlog-config
27
+ ```
28
+
17
29
  ## Usage
18
30
 
19
31
  ```python
@@ -93,6 +105,8 @@ For example, if you wanted to [mimic `OPENAI_LOG` functionality](https://github.
93
105
 
94
106
  ## FastAPI Access Logger
95
107
 
108
+ **Note:** Requires `pip install structlog-config[fastapi]` for FastAPI dependencies.
109
+
96
110
  Structured, simple access log with request timing to replace the default fastapi access log. Why?
97
111
 
98
112
  1. It's less verbose
@@ -104,6 +118,64 @@ Here's how to use it:
104
118
  1. [Disable fastapi's default logging.](https://github.com/iloveitaly/python-starter-template/blob/f54cb47d8d104987f2e4a668f9045a62e0d6818a/main.py#L55-L56)
105
119
  2. [Add the middleware to your FastAPI app.](https://github.com/iloveitaly/python-starter-template/blob/f54cb47d8d104987f2e4a668f9045a62e0d6818a/app/routes/middleware/__init__.py#L63-L65)
106
120
 
121
+ ## Pytest Plugin: Capture Logs on Failure
122
+
123
+ A pytest plugin that captures logs per-test and displays them only when tests fail. This keeps your test output clean while ensuring you have all the debugging information you need when something goes wrong.
124
+
125
+ ### Features
126
+
127
+ - Only shows logs for failing tests (keeps output clean)
128
+ - Captures logs from all test phases (setup, call, teardown)
129
+ - Unique log file per test
130
+ - Optional persistent log storage for debugging
131
+ - Automatically handles `PYTHON_LOG_PATH` environment variable
132
+
133
+ ### Usage
134
+
135
+ Enable the plugin with the `--capture-logs-on-fail` flag:
136
+
137
+ ```bash
138
+ pytest --capture-logs-on-fail
139
+ ```
140
+
141
+ Or enable it permanently in `pytest.ini` or `pyproject.toml`:
142
+
143
+ ```toml
144
+ [tool.pytest.ini_options]
145
+ addopts = ["--capture-logs-on-fail"]
146
+ ```
147
+
148
+ ### Persist Logs to Directory
149
+
150
+ To keep all test logs for later inspection (useful for CI/CD debugging):
151
+
152
+ ```bash
153
+ pytest --capture-logs-dir=./test-logs
154
+ ```
155
+
156
+ This creates a log file for each test and disables automatic cleanup.
157
+
158
+ ### How It Works
159
+
160
+ 1. Sets `PYTHON_LOG_PATH` environment variable to a unique temp file for each test
161
+ 2. Your application logs (via `configure_logger()`) write to this file
162
+ 3. On test failure, the plugin prints the captured logs to stdout
163
+ 4. Log files are cleaned up after the test session (unless `--capture-logs-dir` is used)
164
+
165
+ ### Example Output
166
+
167
+ When a test fails, you'll see:
168
+
169
+ ```
170
+ FAILED tests/test_user.py::test_user_login
171
+
172
+ --- Captured logs for failed test (call): tests/test_user.py::test_user_login ---
173
+ 2025-11-01 18:30:00 [info] User login started user_id=123
174
+ 2025-11-01 18:30:01 [error] Database connection failed timeout=5.0
175
+ ```
176
+
177
+ For passing tests, no log output is shown, keeping your test output clean and focused.
178
+
107
179
  ## iPython
108
180
 
109
181
  Often it's helpful to update logging level within an iPython session. You can do this and make sure all loggers pick up on it.
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "structlog-config"
3
+ version = "0.6.0"
4
+ description = "A comprehensive structlog configuration with sensible defaults for development and production environments, featuring context management, exception formatting, and path prettification."
5
+ keywords = ["logging", "structlog", "json-logging", "structured-logging"]
6
+ readme = "README.md"
7
+ requires-python = ">=3.11"
8
+ dependencies = [
9
+ "orjson>=3.10.15",
10
+ "python-decouple-typed>=3.11.0",
11
+ "python-ipware>=3.0.0",
12
+ "structlog>=25.2.0",
13
+ ]
14
+ urls = { "Repository" = "https://github.com/iloveitaly/structlog-config" }
15
+ authors = [{ name = "Michael Bianco", email = "mike@mikebian.co" }]
16
+
17
+ [project.optional-dependencies]
18
+ fastapi = ["fastapi-ipware>=0.1.0"]
19
+
20
+ [build-system]
21
+ requires = ["uv_build>=0.8.11,<0.9.0"]
22
+ build-backend = "uv_build"
23
+
24
+ [tool.uv.build-backend]
25
+ # avoids the src/ directory structure
26
+ module-root = ""
27
+
28
+ [dependency-groups]
29
+ dev = [
30
+ "fastapi>=0.115.12",
31
+ "httpx>=0.28.1",
32
+ "pytest>=8.3.3",
33
+ "fastapi_ipware>=0.1.0",
34
+ ]
@@ -45,8 +45,7 @@ def log_processors_for_mode(json_logger: bool) -> list[structlog.types.Processor
45
45
  )
46
46
 
47
47
  return [
48
- # add exc_info=True to a log and get a full stack trace attached to it
49
- structlog.processors.format_exc_info,
48
+ # omit `structlog.processors.format_exc_info` so we can use structured logging for exceptions
50
49
  # simple, short exception rendering in prod since sentry is in place
51
50
  # https://www.structlog.org/en/stable/exceptions.html this is a customized version of dict_tracebacks
52
51
  ExceptionRenderer(
@@ -7,7 +7,7 @@ from urllib.parse import quote
7
7
 
8
8
  import structlog
9
9
  from fastapi import FastAPI
10
- from python_ipware import IpWare
10
+ from fastapi_ipware import FastAPIIpWare
11
11
  from starlette.middleware.base import RequestResponseEndpoint
12
12
  from starlette.requests import Request
13
13
  from starlette.responses import Response
@@ -15,9 +15,8 @@ from starlette.routing import Match, Mount
15
15
  from starlette.types import Scope
16
16
  from starlette.websockets import WebSocket
17
17
 
18
- # should name this access "access_log" or something
19
18
  log = structlog.get_logger()
20
- ipw = IpWare()
19
+ ipware = FastAPIIpWare()
21
20
 
22
21
 
23
22
  def get_route_name(app: FastAPI, scope: Scope, prefix: str = "") -> str:
@@ -59,35 +58,17 @@ def client_ip_from_request(request: Request | WebSocket) -> str | None:
59
58
  """
60
59
  Get the client IP address from the request.
61
60
 
62
- Headers are not case-sensitive.
63
-
64
- Uses ipware library to properly extract client IP from various proxy headers.
61
+ Uses fastapi-ipware library to properly extract client IP from various proxy headers.
65
62
  Fallback to direct client connection if no proxy headers found.
66
63
  """
67
- headers = request.headers
68
-
69
- # TODO this seems really inefficient, we should just rewrite the ipware into this repo :/
70
- # Convert Starlette headers to format expected by ipware (HTTP_ prefixed)
71
- # ipware expects headers in WSGI/Django-style meta format where HTTP headers
72
- # are prefixed with "HTTP_" and dashes become underscores.
73
- # See: https://github.com/un33k/python-ipware/blob/main/python_ipware/python_ipware.py#L33-L40
74
- meta_dict = {}
75
- for name, value in headers.items():
76
- # Convert header name to HTTP_ prefixed format
77
- meta_key = f"HTTP_{name.upper().replace('-', '_')}"
78
- meta_dict[meta_key] = value
79
-
80
- # Use ipware to extract IP from headers
81
- ip, trusted_route = ipw.get_client_ip(meta=meta_dict)
64
+ ip, trusted_route = ipware.get_client_ip_from_request(request)
82
65
  if ip:
83
66
  log.debug(
84
67
  "extracted client IP from headers", ip=ip, trusted_route=trusted_route
85
68
  )
86
69
  return str(ip)
87
70
 
88
- # Fallback to direct client connection
89
71
  host = request.client.host if request.client else None
90
-
91
72
  return host
92
73
 
93
74
 
@@ -101,16 +82,8 @@ def is_static_assets_request(scope: Scope) -> bool:
101
82
  Returns:
102
83
  bool: True if the request is for static assets, False otherwise.
103
84
  """
104
- return (
105
- scope["path"].endswith(".css")
106
- or scope["path"].endswith(".js")
107
- # .map files are attempted when devtools are enabled
108
- or scope["path"].endswith(".js.map")
109
- or scope["path"].endswith(".ico")
110
- or scope["path"].endswith(".png")
111
- or scope["path"].endswith(".jpg")
112
- or scope["path"].endswith(".jpeg")
113
- or scope["path"].endswith(".gif")
85
+ return scope["path"].endswith(
86
+ (".css", ".js", ".js.map", ".ico", ".png", ".jpg", ".jpeg", ".gif", ".webp")
114
87
  )
115
88
 
116
89
 
@@ -0,0 +1,222 @@
1
+ """
2
+ Pytest plugin for capturing and displaying logs only on test failures.
3
+
4
+ This plugin integrates with structlog-config's file logging to capture logs per-test
5
+ and display them only when tests fail, keeping output clean for passing tests.
6
+
7
+ Usage:
8
+ 1. Install the plugin (automatically registered via entry point):
9
+ pip install structlog-config[fastapi]
10
+
11
+ 2. Enable in pytest.ini or pyproject.toml:
12
+ [tool.pytest.ini_options]
13
+ addopts = ["--capture-logs-on-fail"]
14
+
15
+ Or enable for a single test run:
16
+ pytest --capture-logs-on-fail
17
+
18
+ 3. Optional: Persist all logs to a directory:
19
+ pytest --capture-logs-dir=/path/to/logs
20
+
21
+ How it works:
22
+ - Sets PYTHON_LOG_PATH to a unique temp file for each test
23
+ - Logs are written to /tmp/<project-name>-pytest-logs-*/test_name.log
24
+ - On test failure, prints captured logs to stdout
25
+ - Cleans up temp files after each test (unless --capture-logs-dir is set)
26
+ - Automatically disabled if PYTHON_LOG_PATH is already set
27
+
28
+ Example output on failure:
29
+ --- Captured logs for failed test: tests/test_foo.py::test_bar ---
30
+ 2025-10-31 23:30:00 [info] Starting test
31
+ 2025-10-31 23:30:01 [error] Something went wrong
32
+ """
33
+
34
+ import logging
35
+ import os
36
+ import re
37
+ import shutil
38
+ import tempfile
39
+ from pathlib import Path
40
+ from typing import Generator
41
+
42
+ import pytest
43
+
44
+ logger = logging.getLogger(__name__)
45
+
46
+ PLUGIN_KEY = pytest.StashKey[dict]()
47
+ SESSION_TMPDIR_KEY = "session_tmpdir"
48
+
49
+
50
+ def sanitize_filename(name: str) -> str:
51
+ """Replace non-filename-safe characters with underscores.
52
+
53
+ Args:
54
+ name: The filename to sanitize (typically a pytest nodeid).
55
+
56
+ Returns:
57
+ A filesystem-safe filename string.
58
+ """
59
+ return re.sub(r"[^A-Za-z0-9_.-]", "_", name)
60
+
61
+
62
+ def pytest_addoption(parser: pytest.Parser) -> None:
63
+ """Register the --capture-logs-on-fail command line option.
64
+
65
+ Args:
66
+ parser: The pytest parser to add options to.
67
+ """
68
+ parser.addoption(
69
+ "--capture-logs-on-fail",
70
+ action="store_true",
71
+ default=False,
72
+ help="Capture logs to a temp file and dump them to stdout on test failure.",
73
+ )
74
+ parser.addoption(
75
+ "--capture-logs-dir",
76
+ action="store",
77
+ default=None,
78
+ help="Directory to persist all test logs (disables automatic cleanup).",
79
+ )
80
+
81
+
82
+ @pytest.hookimpl(tryfirst=True)
83
+ def pytest_configure(config: pytest.Config) -> None:
84
+ """Configure the plugin at pytest startup.
85
+
86
+ Stores configuration state on the config object for use by fixtures and hooks.
87
+
88
+ Args:
89
+ config: The pytest config object.
90
+ """
91
+ logs_dir = config.getoption("--capture-logs-dir")
92
+ enabled = config.getoption("--capture-logs-on-fail") or logs_dir is not None
93
+
94
+ plugin_config = {
95
+ "enabled": enabled,
96
+ "logs_dir": logs_dir,
97
+ "project_name": os.path.basename(str(config.rootdir)),
98
+ }
99
+ config.stash[PLUGIN_KEY] = plugin_config
100
+
101
+
102
+ @pytest.hookimpl(tryfirst=True)
103
+ def pytest_sessionstart(session: pytest.Session) -> None:
104
+ """Create a session-level temp directory for log files.
105
+
106
+ Args:
107
+ session: The pytest session object.
108
+ """
109
+ config = session.config
110
+ plugin_config = config.stash.get(PLUGIN_KEY, {})
111
+
112
+ if not plugin_config.get("enabled"):
113
+ return
114
+
115
+ logs_dir = plugin_config.get("logs_dir")
116
+ if logs_dir:
117
+ tmpdir = Path(logs_dir)
118
+ tmpdir.mkdir(parents=True, exist_ok=True)
119
+ else:
120
+ project_name = plugin_config.get("project_name", "pytest")
121
+ tmpdir = Path(tempfile.mkdtemp(prefix=f"{project_name}-pytest-logs-"))
122
+
123
+ plugin_config[SESSION_TMPDIR_KEY] = tmpdir
124
+ config.stash[PLUGIN_KEY] = plugin_config
125
+
126
+
127
+ @pytest.hookimpl(trylast=True)
128
+ def pytest_sessionfinish(session: pytest.Session) -> None:
129
+ """Clean up session-level temp directory unless --capture-logs-dir was used.
130
+
131
+ Args:
132
+ session: The pytest session object.
133
+ """
134
+ config = session.config
135
+ plugin_config = config.stash.get(PLUGIN_KEY, {})
136
+
137
+ if not plugin_config.get("enabled"):
138
+ return
139
+
140
+ logs_dir = plugin_config.get("logs_dir")
141
+ tmpdir = plugin_config.get(SESSION_TMPDIR_KEY)
142
+
143
+ if tmpdir and not logs_dir:
144
+ shutil.rmtree(tmpdir, ignore_errors=True)
145
+
146
+
147
+ @pytest.fixture(autouse=True)
148
+ def capture_logs_on_fail(request: pytest.FixtureRequest) -> Generator[None, None, None]:
149
+ """Set up per-test log capture to a temporary file.
150
+
151
+ This fixture runs automatically for every test when --capture-logs-on-fail is enabled.
152
+ It sets PYTHON_LOG_PATH to redirect logs to a unique temp file, then cleans up after.
153
+
154
+ Args:
155
+ request: The pytest request fixture providing test context.
156
+
157
+ Yields:
158
+ Control back to the test, then handles cleanup after test completion.
159
+ """
160
+ config = request.config
161
+ plugin_config = config.stash.get(PLUGIN_KEY, {})
162
+
163
+ if not plugin_config.get("enabled"):
164
+ yield
165
+ return
166
+
167
+ if "PYTHON_LOG_PATH" in os.environ:
168
+ logger.warning(
169
+ "PYTHON_LOG_PATH is already set; pytest-capture-logs-on-fail plugin is disabled for this test."
170
+ )
171
+ yield
172
+ return
173
+
174
+ tmpdir = plugin_config.get(SESSION_TMPDIR_KEY)
175
+ if not tmpdir:
176
+ logger.warning("Session temp directory not initialized")
177
+ yield
178
+ return
179
+
180
+ test_name = sanitize_filename(request.node.nodeid)
181
+ log_file = tmpdir / f"{test_name}.log"
182
+
183
+ original_log_path = os.environ.get("PYTHON_LOG_PATH")
184
+ os.environ["PYTHON_LOG_PATH"] = str(log_file)
185
+
186
+ logger.info(f"Logs for test '{request.node.nodeid}' will be stored at: {log_file}")
187
+
188
+ yield
189
+
190
+ setattr(request.node, "_pytest_log_file", str(log_file))
191
+
192
+ if original_log_path is not None:
193
+ os.environ["PYTHON_LOG_PATH"] = original_log_path
194
+ else:
195
+ del os.environ["PYTHON_LOG_PATH"]
196
+
197
+
198
+ def pytest_runtest_makereport(item: pytest.Item, call: pytest.CallInfo) -> None:
199
+ """Hook called after each test phase to create test reports.
200
+
201
+ On test failure, reads and prints the captured log file to stdout.
202
+ Handles failures in setup, call, and teardown phases.
203
+
204
+ Args:
205
+ item: The test item being reported on.
206
+ call: The call object containing execution info and any exception.
207
+ """
208
+ config = item.config
209
+ plugin_config = config.stash.get(PLUGIN_KEY, {})
210
+
211
+ if not plugin_config.get("enabled"):
212
+ return
213
+
214
+ if call.excinfo is not None:
215
+ log_file = getattr(item, "_pytest_log_file", None)
216
+ if log_file and os.path.exists(log_file):
217
+ with open(log_file, "r") as f:
218
+ logs = f.read()
219
+
220
+ if logs.strip():
221
+ phase = call.when
222
+ print(f"\n--- Captured logs for failed test ({phase}): {item.nodeid} ---\n{logs}\n")
@@ -11,7 +11,6 @@ from decouple import config
11
11
 
12
12
  from .constants import PYTHONASYNCIODEBUG
13
13
  from .env_config import get_custom_logger_config
14
- from .environments import is_production, is_staging
15
14
  from .levels import (
16
15
  compare_log_levels,
17
16
  get_environment_log_level_as_string,
@@ -49,14 +48,18 @@ def redirect_stdlib_loggers(json_logger: bool):
49
48
 
50
49
  default_processors = get_default_processors(json_logger=json_logger)
51
50
 
51
+ if json_logger:
52
+ # don't use ORJSON here, as the stdlib formatter chain expects a str not a bytes
53
+ final_renderer = structlog.processors.JSONRenderer(sort_keys=True)
54
+ else:
55
+ # use the default renderer, which is the last processor
56
+ final_renderer = default_processors[-1]
57
+
52
58
  formatter = ProcessorFormatter(
53
59
  processors=[
54
60
  # required to strip extra keys that the structlog stdlib bindings add in
55
61
  structlog.stdlib.ProcessorFormatter.remove_processors_meta,
56
- default_processors[-1]
57
- if not is_production() and not is_staging()
58
- # don't use ORJSON here, as the stdlib formatter chain expects a str not a bytes
59
- else structlog.processors.JSONRenderer(sort_keys=True),
62
+ final_renderer,
60
63
  ],
61
64
  # processors unique to stdlib logging
62
65
  foreign_pre_chain=[
@@ -1,9 +1,11 @@
1
1
  """
2
+ Adds a TRACE log level to the standard logging module and structlog.
3
+
4
+ Some people believe that the standard log levels are not enough, and I'm with them.
5
+
2
6
  Adapted from:
3
7
  - https://github.com/willmcgugan/httpx/blob/973d1ed4e06577d928061092affe8f94def03331/httpx/_utils.py#L231
4
8
  - https://github.com/vladmandic/sdnext/blob/d5d857aa961edbc46c9e77e7698f2e60011e7439/installer.py#L154
5
-
6
- TODO this is not fully integrated into the codebase
7
9
  """
8
10
 
9
11
  import logging
@@ -1,61 +0,0 @@
1
- [project]
2
- name = "structlog-config"
3
- version = "0.5.0"
4
- description = "A comprehensive structlog configuration with sensible defaults for development and production environments, featuring context management, exception formatting, and path prettification."
5
- keywords = ["logging", "structlog", "json-logging", "structured-logging"]
6
- readme = "README.md"
7
- requires-python = ">=3.10"
8
- dependencies = [
9
- "orjson>=3.10.15",
10
- "python-decouple-typed>=3.11.0",
11
- "python-ipware>=3.0.0",
12
- "structlog>=25.2.0",
13
- ]
14
- authors = [{ name = "Michael Bianco", email = "mike@mikebian.co" }]
15
- urls = { "Repository" = "https://github.com/iloveitaly/structlog-config" }
16
-
17
- [build-system]
18
- requires = ["uv_build>=0.8.11,<0.9.0"]
19
- build-backend = "uv_build"
20
-
21
- [tool.uv.build-backend]
22
- # avoids the src/ directory structure
23
- module-root = ""
24
-
25
- [dependency-groups]
26
- debugging-extras = [
27
- "colorama>=0.4.6",
28
- "datamodel-code-generator>=0.28.5",
29
- "debugpy>=1.8.13",
30
- "docrepr>=0.2.0",
31
- "funcy-pipe>=0.11.1",
32
- "httpdbg>=1.1.2",
33
- "icecream>=2.1.4",
34
- "ipdb",
35
- "ipython>=8.34.0",
36
- "ipython-autoimport>=0.5.1",
37
- "ipython-ctrlr-fzf>=0.2.1",
38
- "ipython-playground>=0.2.0",
39
- "ipython-suggestions",
40
- "ipythonclipboard>=1.0b2",
41
- "jedi>=0.19.2",
42
- "pdbr[ipython]>=0.9.0",
43
- "pipdeptree>=2.26.0",
44
- "pre-commit>=4.2.0",
45
- "pretty-traceback",
46
- "pudb>=2024.1.3",
47
- "py-spy>=0.4.0",
48
- "pyfzf>=0.3.1",
49
- "pytest-fzf>=0.1.2.post1",
50
- "rich>=14.0.0",
51
- "rpdb>=0.2.0",
52
- "sqlparse>=0.5.3",
53
- "uv-development-toggle>=0.4.0",
54
- ]
55
- dev = ["fastapi>=0.115.12", "httpx>=0.28.1", "pytest>=8.3.3"]
56
-
57
- [tool.uv.sources]
58
- ipdb = { git = "https://github.com/iloveitaly/ipdb", rev = "support-executables" }
59
- pdbr = { git = "https://github.com/iloveitaly/pdbr", rev = "ipython-9.x" }
60
- pretty-traceback = { git = "https://github.com/iloveitaly/pretty-traceback.git", rev = "custom" }
61
- ipython-suggestions = { git = "https://github.com/iloveitaly/ipython-suggestions.git", rev = "ipython-9.x" }