Repository: litestar-org/litestar

Issue:
Bug: Structlog example no longer works
Me again. Sorry 🙈 

**Describe the bug**
Running the structlog example [here](https://starlite-api.github.io/starlite/1.48/usage/0-the-starlite-app/?h=structlog#using-structlog) results in an internal server error as of v1.45 (I think)

```
{"status_code":500,"detail":"TypeError(\"encode_json() got an unexpected keyword argument 'default'\")"}
```

The default encoder was changed [here](https://github.com/starlite-api/starlite/pull/891/files#diff-6b2294023eb60948cd9f742e4930255a72254daf74f9e3157df8d479a685b123R213)
Which doesn't accept the `default` argument given [here](https://github.com/hynek/structlog/blob/main/src/structlog/processors.py#L318)

I'm not sure if it's a structlog problem or a starlite problem.

Maybe the solution is to rename `enc_hook` to `default` then it mirrors the signature of `json.dumps`? I'm not sure, to be honest.


**To Reproduce**
Run the structlog example in the documentation:
```python
from starlite import Starlite, StructLoggingConfig, Request, get


@get("/")
def my_router_handler(request: Request) -> None:
    request.logger.info("inside a request")
    return None


logging_config = StructLoggingConfig()

app = Starlite(route_handlers=[my_router_handler], logging_config=logging_config)
```

**Additional context**
Add any other context about the problem here.



Discussion:
> Me again. Sorry :see_no_evil:

Don't be, every bug report is very welcome!

> Maybe the solution is to rename `enc_hook` to `default` then it mirrors the signature of json.dumps

Yes, that would be the best solution. Wanna add  a PR?

This also definitely should have been caught by our tests.



Resolving patch:
diff --git a/starlite/utils/serialization.py b/starlite/utils/serialization.py
--- a/starlite/utils/serialization.py
+++ b/starlite/utils/serialization.py
@@ -93,19 +93,19 @@ def dec_hook(type_: Any, value: Any) -> Any:  # pragma: no cover
 _msgspec_msgpack_decoder = msgspec.msgpack.Decoder(dec_hook=dec_hook)
 
 
-def encode_json(obj: Any, enc_hook: Optional[Callable[[Any], Any]] = default_serializer) -> bytes:
+def encode_json(obj: Any, default: Optional[Callable[[Any], Any]] = default_serializer) -> bytes:
     """Encode a value into JSON.
 
     Args:
         obj: Value to encode
-        enc_hook: Optional callable to support non-natively supported types
+        default: Optional callable to support non-natively supported types.
 
     Returns:
         JSON as bytes
     """
-    if enc_hook is None or enc_hook is default_serializer:
+    if default is None or default is default_serializer:
         return _msgspec_json_encoder.encode(obj)
-    return msgspec.json.encode(obj, enc_hook=enc_hook)
+    return msgspec.json.encode(obj, enc_hook=default)
 
 
 def decode_json(raw: Union[str, bytes]) -> Any:


Test patch:
diff --git a/tests/logging_config/test_structlog_config.py b/tests/logging_config/test_structlog_config.py
--- a/tests/logging_config/test_structlog_config.py
+++ b/tests/logging_config/test_structlog_config.py
@@ -1,32 +1,43 @@
+from pytest import CaptureFixture  # noqa: TC002
 from structlog.processors import JSONRenderer
-from structlog.testing import capture_logs
 from structlog.types import BindableLogger
 
 from starlite.config import StructLoggingConfig
 from starlite.testing import create_test_client
+from starlite.utils.serialization import decode_json, encode_json
 
+# structlog.testing.capture_logs changes the processors
+# Because we want to test processors, use capsys instead
 
-def test_structlog_config() -> None:
-    with create_test_client([], logging_config=StructLoggingConfig()) as client, capture_logs() as cap_logs:
+
+def test_structlog_config_default(capsys: CaptureFixture) -> None:
+    with create_test_client([], logging_config=StructLoggingConfig()) as client:
         assert client.app.logger
         assert isinstance(client.app.logger, BindableLogger)
         client.app.logger.info("message", key="value")
-        assert len(cap_logs) == 1
-        assert cap_logs[0] == {"key": "value", "event": "message", "log_level": "info"}
+
+        log_messages = [decode_json(x) for x in capsys.readouterr().out.splitlines()]
+        assert len(log_messages) == 1
+
+        # Format should be: {event: message, key: value, level: info, timestamp: isoformat}
+        log_messages[0].pop("timestamp")  # Assume structlog formats timestamp correctly
+        assert log_messages[0] == {"event": "message", "key": "value", "level": "info"}
 
 
-def test_structlog_config_specify_processors() -> None:
-    logging_config = StructLoggingConfig(processors=[JSONRenderer()])
+def test_structlog_config_specify_processors(capsys: CaptureFixture) -> None:
+    logging_config = StructLoggingConfig(processors=[JSONRenderer(encode_json)])
 
-    with create_test_client([], logging_config=logging_config) as client, capture_logs() as cap_logs:
+    with create_test_client([], logging_config=logging_config) as client:
         assert client.app.logger
         assert isinstance(client.app.logger, BindableLogger)
 
         client.app.logger.info("message1", key="value1")
-        assert len(cap_logs) == 1
-        assert cap_logs[0] == {"key": "value1", "event": "message1", "log_level": "info"}
-
         # Log twice to make sure issue #882 doesn't appear again
         client.app.logger.info("message2", key="value2")
-        assert len(cap_logs) == 2
-        assert cap_logs[1] == {"key": "value2", "event": "message2", "log_level": "info"}
+
+        log_messages = [decode_json(x) for x in capsys.readouterr().out.splitlines()]
+
+        assert log_messages == [
+            {"key": "value1", "event": "message1"},
+            {"key": "value2", "event": "message2"},
+        ]