Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

on:
push:
branches: ["main", "develop"]
pull_request:
branches: ["main", "develop"]

jobs:
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip

- name: Install dependencies
run: pip install -e ".[dev,async]"

- name: Run tests
run: pytest tests/ -v --tb=short
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: read

jobs:
# ── 1. Run tests before publishing ────────────────────────────────────────
test:
name: Test before release
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install dependencies
run: pip install -e ".[dev,async]"

- name: Run tests
run: pytest tests/ -v --tb=short

# ── 2. Build source distribution and wheel ────────────────────────────────
build:
name: Build distribution
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install build
run: pip install build

- name: Build sdist and wheel
run: python -m build

- name: Verify tag matches package version
run: |
TAG="${GITHUB_REF_NAME#v}"
VERSION=$(python -c "
import re, pathlib
content = pathlib.Path('pyproject.toml').read_text()
print(re.search(r'^version\s*=\s*\"(.+?)\"', content, re.MULTILINE).group(1))
")
echo "Tag: $TAG | Package version: $VERSION"
if [ "$TAG" != "$VERSION" ]; then
echo "ERROR: tag '$TAG' does not match package version '$VERSION'"
exit 1
fi

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/

# ── 3. Publish to PyPI via OIDC Trusted Publisher ─────────────────────────
publish:
name: Publish to PyPI
runs-on: ubuntu-latest
needs: build
environment: pypi

permissions:
id-token: write # required for OIDC trusted publisher

steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
54 changes: 53 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,57 @@ 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).

## [0.8.4] - 2026-03-21

### Added

- `AsyncLogTideClient`: full async client using `aiohttp` with the same API as the
sync client — supports `async with`, `await client.start()`, and all logging,
flush, query, and stream methods as coroutines (`pip install logtide-sdk[async]`)
- `LogTideHandler`: standard `logging.Handler` for drop-in integration with Python's
built-in logging module — forwards records to LogTide with structured exception
metadata when `exc_info=True` is used
- `PayloadLimitsOptions`: configurable safeguards against 413 errors — per-field size
cap, total entry size cap, named field exclusion, and automatic base64 removal
- `LogTideStarletteMiddleware`: standalone Starlette ASGI middleware independent of
FastAPI (`pip install logtide-sdk[starlette]`)
- `serialize_exception()` exported at top level for use in custom integrations
- `payload_limits` field on `ClientOptions`

### Changed

- **BREAKING** API paths updated to match v1 server contract:
- `POST /api/logs` → `POST /api/v1/ingest`
- `GET /api/logs` → `GET /api/v1/logs`
- `GET /api/logs/trace/{id}` → `GET /api/v1/logs/trace/{id}`
- `GET /api/logs/stats` → `GET /api/v1/logs/aggregated`
- `GET /api/logs/stream` → `GET /api/v1/logs/stream`
- **BREAKING** Auth header changed from `Authorization: Bearer <key>` to `X-API-Key: <key>`
- **BREAKING** Error metadata key changed from `"error"` to `"exception"`; value is now a
structured object with `type`, `message`, `language`, `stacktrace` (array of
`{file, function, line}` frames), and `raw`
- **BREAKING** `stream()` no longer blocks — it runs in a background daemon thread and
returns a `Callable[[], None]` stop function immediately
- **BREAKING** Buffer overflow no longer raises `BufferFullError`; logs are silently
dropped and `logs_dropped` is incremented (`BufferFullError` class is kept for
backwards-compatible catch blocks)
- `requests.Session` is now created once and reused across all HTTP calls for
connection reuse and reduced TCP overhead
- `datetime.utcnow()` replaced with `datetime.now(timezone.utc)` throughout;
`LogEntry.time` now includes `+00:00` timezone suffix (ISO 8601 compliant)
- Middleware `__init__.py` now uses per-framework `try/except` guards — importing
`logtide_sdk.middleware` no longer fails if only a subset of frameworks are installed

### Fixed

- Flask, Django, and FastAPI middleware `_log_error` methods were passing raw
`Exception` objects into the metadata dict instead of serializing them — exceptions
are now serialized via `serialize_exception()`
- `log()` triggered `flush()` while holding `_buffer_lock`, causing a potential
deadlock under concurrent access — flush is now triggered outside the lock
- `__version__` in `__init__.py` was incorrectly set to `"0.1.0"` despite the
package being at `0.1.2`

## [0.1.0] - 2026-01-13

### Added
Expand All @@ -28,4 +79,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- FastAPI middleware for auto-logging HTTP requests
- Full type hints support for Python 3.8+

[0.1.0]: https://github.com/logtide-dev/logtide-sdk-python/releases/tag/v0.1.0
[0.8.4]: https://github.com/logtide-dev/logtide-python/compare/v0.1.0...v0.8.4
[0.1.0]: https://github.com/logtide-dev/logtide-python/releases/tag/v0.1.0
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Thank you for your interest in contributing!

1. Clone the repository:
```bash
git clone https://github.com/logtide-dev/logtide-sdk-python.git
git clone https://github.com/logtide-dev/logtide-python.git
cd logtide-sdk-python
```

Expand Down
Loading
Loading