# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2026-03-04

### Added

- **OpenTelemetry context injection** — `trace_id` and `span_id` are automatically
  added to every log entry when `opentelemetry-api` is installed and an active span
  exists. Controlled by `enable_otel_context` (default `True`).
- **Temporal context injection** — `workflow_id`, `activity_type`, `task_queue`, and
  `attempt` are automatically added when `temporalio` is installed and code runs
  inside a Temporal workflow or activity. Controlled by `enable_temporal_context`
  (default `True`).
- **`BoundConfigurableLogger`** — `bind()` now returns a wrapper that preserves the
  full `ConfigurableLogger` API (including `error(exception=...)` and Sentry
  integration) instead of a raw `structlog.BoundLogger`. Also supports `unbind()`.
- **Configurable JSON indentation** — new `json_indent` parameter (default `4`,
  preserving existing output). Set to `None` for compact single-line JSON in
  production to reduce log volume.
- **Optional dependency extras** — `pip install jhlogger[otel]`,
  `pip install jhlogger[temporal]`, or `pip install jhlogger[observability]` for
  both.

### Changed

- **Per-instance structlog configuration** — `ConfigurableLogger` now uses
  `structlog.wrap_logger()` instead of the global `structlog.configure()`. Creating
  multiple logger instances no longer overwrites each other's processor chains.
  *This is a behavioral change*: code that relied on jhlogger setting global
  structlog configuration will need to call `structlog.configure()` separately.
- **Dynamic caller detection** — `_get_caller_info()` now walks the stack
  dynamically (skipping `jhlogger`, `structlog`, and `logging` frames) instead of
  using a hardcoded 3-frame skip. This produces more accurate caller information,
  especially inside Temporal activities and deeply nested call chains.
- **Lazy optional imports** — `sentry-sdk` and `watchtower` are now imported lazily.
  `import jhlogger` no longer raises `ImportError` if these packages are absent
  (they remain hard dependencies in `pyproject.toml` so existing installs are
  unaffected).

### Fixed

- Version mismatch between `pyproject.toml` (was 1.0.1) and `__init__.py` (was
  1.0.0); both now read 1.1.0.
- **Multiple logger instances with same name interference** — `ConfigurableLogger`
  instances with identical names now use unique internal stdlib logger names to
  prevent handler clearing and log level conflicts. Each instance maintains
  independent configuration while displaying the user-provided name in log output.

### Async CloudWatch Guidance

The `watchtower` CloudWatch handler performs synchronous HTTP I/O, which can block
async event loops (e.g. in Temporal activities). For async workloads the recommended
pattern is to ship logs to CloudWatch via the **OpenTelemetry Collector** rather
than directly from the application. This avoids blocking the event loop and
centralises log routing.

## [1.0.0] - 2025-09-18

### Added

- Initial release of ConfigurableLogger
- Configurable log levels with dynamic runtime changes
- Structured JSON output with 4-space indentation and sorted keys
- Full traceback support for DEBUG level logging
- Exception details capture for ERROR level logging
- Automatic caller information detection (filename, function, class, line number)
- Third-party service integration (CloudWatch, Sentry, Bugsnag)
- Relative file paths for enhanced security
- Environment-aware configuration
- Support for bound context logging
- Comprehensive test suite with 92%+ coverage
- Complete documentation and examples
- MIT License

### Features

- **Security**: Uses relative file paths to prevent system information exposure
- **Performance**: Efficient CloudWatch batching and lazy evaluation
- **Flexibility**: Configurable processors and custom data fields
- **Reliability**: Comprehensive error handling and fallback mechanisms
- **Usability**: Simple API with both convenience functions and class-based usage

### Dependencies

- structlog >= 23.0.0
- watchtower >= 3.0.0
- sentry-sdk >= 1.0.0

### Python Support

- Python 3.8+
- Tested on Python 3.8, 3.9, 3.10, 3.11, 3.12
