Skip to content

Commit a7247ac

Browse files
Fix CI failures: lint, test deps, DCO action, Repolinter config
- Fix 14 ruff lint errors (import sorting, unused vars/imports) and auto-format all files with ruff - Add starlette to dev dependencies for middleware tests - Replace broken dcoapp/app@v1 with christophebedard/dco-check@v0.5.0 - Replace 404 remote repolinter config with local .github/repolinter.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c15c11e commit a7247ac

20 files changed

+564
-368
lines changed

.github/repolinter.json

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/todogroup/repolinter/master/rulesets/schema.json",
3+
"version": 2,
4+
"axioms": {},
5+
"rules": {
6+
"license-file-exists": {
7+
"level": "error",
8+
"rule": {
9+
"type": "file-existence",
10+
"options": {
11+
"globsAny": ["LICENSE*", "COPYING*"]
12+
}
13+
}
14+
},
15+
"readme-file-exists": {
16+
"level": "error",
17+
"rule": {
18+
"type": "file-existence",
19+
"options": {
20+
"globsAny": ["README*"]
21+
}
22+
}
23+
},
24+
"contributing-file-exists": {
25+
"level": "warning",
26+
"rule": {
27+
"type": "file-existence",
28+
"options": {
29+
"globsAny": ["CONTRIBUTING*"]
30+
}
31+
}
32+
},
33+
"changelog-file-exists": {
34+
"level": "warning",
35+
"rule": {
36+
"type": "file-existence",
37+
"options": {
38+
"globsAny": ["CHANGELOG*"]
39+
}
40+
}
41+
},
42+
"code-of-conduct-file-exists": {
43+
"level": "warning",
44+
"rule": {
45+
"type": "file-existence",
46+
"options": {
47+
"globsAny": ["CODE_OF_CONDUCT*", "CODE-OF-CONDUCT*", ".github/CODE_OF_CONDUCT*"]
48+
}
49+
}
50+
},
51+
"security-file-exists": {
52+
"level": "warning",
53+
"rule": {
54+
"type": "file-existence",
55+
"options": {
56+
"globsAny": ["SECURITY*", ".github/SECURITY*"]
57+
}
58+
}
59+
},
60+
"notice-file-exists": {
61+
"level": "warning",
62+
"rule": {
63+
"type": "file-existence",
64+
"options": {
65+
"globsAny": ["NOTICE*"]
66+
}
67+
}
68+
},
69+
"license-detectable-by-licensee": {
70+
"level": "warning",
71+
"rule": {
72+
"type": "license-detectable-by-licensee",
73+
"options": {}
74+
}
75+
}
76+
}
77+
}

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,6 @@ jobs:
101101
with:
102102
fetch-depth: 0
103103
- name: DCO check
104-
uses: dcoapp/app@v1
104+
uses: christophebedard/dco-check@v0.5.0
105+
env:
106+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/repolinter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ jobs:
2121
- name: Run Repolinter
2222
uses: todogroup/repolinter-action@v1
2323
with:
24-
config_url: https://raw.githubusercontent.com/lfai/foundation/main/repolinter.json
24+
config_file: .github/repolinter.json

README.md

Lines changed: 105 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,138 @@
44
[![PyPI version](https://img.shields.io/pypi/v/botanu)](https://pypi.org/project/botanu/)
55
[![Python](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12%20|%203.13-blue)](https://www.python.org/)
66
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
7+
[![LF AI & Data](https://img.shields.io/badge/LF%20AI%20%26%20Data-member-blue)](https://lfaidata.foundation/)
78

8-
OpenTelemetry-native run-level cost attribution for AI workflows.
9+
**Run-level cost attribution for AI workflows, built on OpenTelemetry.**
910

10-
## Overview
11+
Botanu adds **runs** on top of distributed tracing. A run represents one business transaction that may span multiple LLM calls, database queries, and microservices. By correlating every operation to a stable `run_id`, you get per-transaction cost attribution without sampling artifacts.
1112

12-
Botanu adds **runs** on top of distributed tracing. A run represents a single business transaction that may span multiple LLM calls, database queries, and services. By correlating all operations to a stable `run_id`, you get accurate cost attribution without sampling artifacts.
13+
## How It Works
14+
15+
```
16+
User Request
17+
|
18+
v
19+
Entry Service Intermediate Service LLM / DB
20+
@botanu_use_case --> enable() propagates --> auto-instrumented
21+
creates run_id run_id via W3C Baggage spans tagged with run_id
22+
```
23+
24+
1. **Entry point** creates a `run_id` with `@botanu_use_case`
25+
2. **Every service** calls `enable()` to propagate the `run_id` via W3C Baggage
26+
3. **All spans** across all services share the same `run_id`
27+
4. **Traces export** to your OTel Collector via OTLP (configured by environment variable)
1328

1429
## Quick Start
1530

31+
### Install
32+
33+
```bash
34+
pip install botanu
35+
```
36+
37+
One install. Includes OTel SDK, OTLP exporter, and auto-instrumentation for 50+ libraries.
38+
39+
### Instrument Your Code
40+
41+
**Entry service** (where the workflow begins):
42+
1643
```python
1744
from botanu import enable, botanu_use_case
1845

19-
enable(service_name="my-service")
46+
enable() # reads config from env vars
2047

21-
@botanu_use_case(name="my_workflow")
22-
def my_function():
23-
data = db.query(...)
24-
result = llm.complete(...)
48+
@botanu_use_case(name="Customer Support")
49+
async def handle_ticket(ticket_id: str):
50+
data = await db.query(ticket_id)
51+
result = await llm.complete(data)
2552
return result
2653
```
2754

28-
## Installation
55+
**Every other service** (intermediate, downstream):
2956

30-
```bash
31-
pip install "botanu[all]"
57+
```python
58+
from botanu import enable
59+
60+
enable() # propagates run_id from incoming request
3261
```
3362

34-
| Extra | Description |
35-
|-------|-------------|
36-
| `sdk` | OpenTelemetry SDK + OTLP exporter |
37-
| `instruments` | Auto-instrumentation for HTTP, databases |
38-
| `genai` | Auto-instrumentation for LLM providers |
39-
| `all` | All of the above (recommended) |
63+
That's it. No collector endpoint in code. No manual span creation.
4064

41-
## What Gets Auto-Instrumented
65+
### Configure via Environment Variables
4266

43-
When you install `botanu[all]`, the following are automatically tracked:
67+
All configuration is via environment variables. **Zero hardcoded values in code.**
4468

45-
- **LLM Providers** — OpenAI, Anthropic, Vertex AI, Bedrock, Azure OpenAI
46-
- **Databases** — PostgreSQL, MySQL, SQLite, MongoDB, Redis
47-
- **HTTP** — requests, httpx, urllib3, aiohttp
48-
- **Frameworks** — FastAPI, Flask, Django, Starlette
49-
- **Messaging** — Celery, Kafka
69+
| Variable | Description | Default |
70+
|----------|-------------|---------|
71+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Collector endpoint | `http://localhost:4318` |
72+
| `OTEL_SERVICE_NAME` | Service name | `unknown_service` |
73+
| `BOTANU_ENVIRONMENT` | Deployment environment | `production` |
5074

51-
No manual instrumentation required.
75+
```yaml
76+
# docker-compose.yml / Kubernetes deployment
77+
environment:
78+
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
79+
- OTEL_SERVICE_NAME=my-service
80+
```
5281
53-
## Kubernetes Deployment
82+
See [Configuration Reference](./docs/getting-started/configuration.md) for all options.
5483
55-
For large-scale deployments (2000+ services):
84+
## Auto-Instrumentation
5685
57-
| Service Type | Code Change | Kubernetes Config |
58-
|--------------|-------------|-------------------|
59-
| Entry point | `@botanu_use_case` decorator | Annotation |
60-
| Intermediate | None | Annotation only |
86+
Everything is included and auto-detected. If the library is in your dependencies, it gets instrumented:
6187
62-
```yaml
63-
# Intermediate services - annotation only, no code changes
64-
metadata:
65-
annotations:
66-
instrumentation.opentelemetry.io/inject-python: "true"
67-
```
88+
| Category | Libraries |
89+
|----------|-----------|
90+
| **LLM Providers** | OpenAI, Anthropic, Vertex AI, Google GenAI, LangChain, Ollama, CrewAI |
91+
| **Web Frameworks** | FastAPI, Flask, Django, Starlette, Falcon, Pyramid, Tornado |
92+
| **HTTP Clients** | requests, httpx, urllib3, aiohttp |
93+
| **Databases** | PostgreSQL (psycopg2/3, asyncpg), MySQL, SQLite, MongoDB, Redis, SQLAlchemy, Elasticsearch, Cassandra |
94+
| **Messaging** | Celery, Kafka, RabbitMQ (pika) |
95+
| **AWS** | botocore, boto3 (SQS) |
96+
| **gRPC** | Client + Server |
97+
| **Runtime** | logging, threading, asyncio |
98+
99+
No manual instrumentation required. Libraries not installed are silently skipped.
100+
101+
## Kubernetes at Scale
102+
103+
For large deployments (2000+ services), only entry points need code changes:
68104
69-
Auto-instrumentation captures all HTTP calls including retries (requests, httpx, aiohttp, urllib3).
105+
| Service Type | Code Change | Configuration |
106+
|--------------|-------------|---------------|
107+
| Entry point | `@botanu_use_case` decorator | `OTEL_EXPORTER_OTLP_ENDPOINT` env var |
108+
| Intermediate | `enable()` call only | `OTEL_EXPORTER_OTLP_ENDPOINT` env var |
70109

71110
See [Kubernetes Deployment Guide](./docs/integration/kubernetes.md) for details.
72111

112+
## Architecture
113+
114+
```
115+
+---------+ +---------+ +---------+
116+
| Service | --> | Service | --> | Service |
117+
| enable()| --> | enable()| --> | enable()|
118+
+---------+ +---------+ +---------+
119+
| | |
120+
v v v
121+
+-------------------------------------+
122+
| OTel Collector (OTLP) |
123+
+-------------------------------------+
124+
| | |
125+
v v v
126+
Jaeger/Tempo Prometheus Your Backend
127+
```
128+
129+
The SDK is a thin layer on OpenTelemetry:
130+
- **SDK**: Generates `run_id`, propagates context, auto-instruments
131+
- **Collector**: PII redaction, cardinality limits, routing, vendor enrichment
132+
73133
## Documentation
74134
75-
- [Getting Started](./docs/getting-started/)
76-
- [Concepts](./docs/concepts/)
77-
- [Integration](./docs/integration/)
78-
- [API Reference](./docs/api/)
135+
- [Getting Started](./docs/getting-started/) - Installation, quickstart, configuration
136+
- [Concepts](./docs/concepts/) - Runs, context propagation, cost attribution
137+
- [Integration](./docs/integration/) - Auto-instrumentation, Kubernetes, collector setup
138+
- [API Reference](./docs/api/) - `enable()`, `@botanu_use_case`, `emit_outcome()`
79139
80140
## Requirements
81141
@@ -84,7 +144,9 @@ See [Kubernetes Deployment Guide](./docs/integration/kubernetes.md) for details.
84144
85145
## Contributing
86146
87-
See [CONTRIBUTING.md](./CONTRIBUTING.md). This project uses DCO sign-off.
147+
We welcome contributions. See [CONTRIBUTING.md](./CONTRIBUTING.md).
148+
149+
This project follows the [Developer Certificate of Origin (DCO)](https://developercertificate.org/). Sign off your commits:
88150
89151
```bash
90152
git commit -s -m "Your commit message"

0 commit comments

Comments
 (0)