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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Initial open-source release
- `enable()` / `disable()` bootstrap
- `@botanu_use_case` decorator with UUIDv7 run_id
- `emit_outcome()` and `set_business_context()` span helpers
- `RunContextEnricher` span processor
- LLM tracking with OTel GenAI semconv alignment
- Data tracking for database, storage, and messaging
- Resource detection for K8s, AWS, GCP, Azure, serverless
- Auto-instrumentation for 20+ libraries
- Optional extras: `[sdk]`, `[instruments]`, `[genai]`, `[carriers]`, `[all]`

[Unreleased]: https://github.com/botanu-ai/botanu-sdk-python/compare/v0.0.0...HEAD
3 changes: 3 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Botanu Code of Conduct

In the interest of fostering an open and welcoming environment, we as contributors and maintainers agree to abide by the Code of Conduct available at https://lfprojects.org/policies/code-of-conduct/
5 changes: 5 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#MAINTAINERS Following is the current list of maintainers on this project

The maintainers are listed in alphabetical order.

[@deborahjacob-botanu] https://github.com/deborahjacob-botanu (Deborah Jacob)
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Botanu SDK for Python

[![CI](https://github.com/botanu-ai/botanu-sdk-python/actions/workflows/ci.yml/badge.svg)](https://github.com/botanu-ai/botanu-sdk-python/actions/workflows/ci.yml)
[![PyPI version](https://badge.fury.io/py/botanu.svg)](https://pypi.org/project/botanu/)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/botanu-ai/botanu-sdk-python/badge)](https://scorecard.dev/viewer/?uri=github.com/botanu-ai/botanu-sdk-python)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)

OpenTelemetry-native **run-level cost attribution** for AI workflows.

## Overview

Botanu adds **runs** on top of distributed tracing. A run represents a single business execution that may span multiple traces, retries, and services. By correlating all spans to a stable `run_id`, you get accurate cost attribution without sampling artifacts.

## Quick Start

```python
from botanu import enable, botanu_use_case, emit_outcome

enable(service_name="my-app")

@botanu_use_case(name="Customer Support")
async def handle_ticket(ticket_id: str):
result = await process_ticket(ticket_id)
emit_outcome("success", value_type="tickets_resolved", value_amount=1)
return result
```

## Installation

```bash
pip install botanu # Core (opentelemetry-api only)
pip install botanu[sdk] # + OTel SDK + OTLP exporter
pip install botanu[all] # Everything including GenAI instrumentation
```

## Documentation

Full documentation is available at [docs.botanu.ai](https://docs.botanu.ai) and in the [`docs/`](./docs/) folder.

## Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md). This project uses [DCO](./DCO) sign-off.

## License

[Apache-2.0](./LICENSE) — see [NOTICE](./NOTICE) for attribution.
9 changes: 9 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Security Policy

## Supported Versions

Please upgrade to latest stable version of Botanu which will have know security issues addressed.

## Reporting a Vulnerability

Please report security vulnerabilities privately to the Botanu [maintainer team] (https://github.com/monocle2ai/monocle/blob/main/MAINTAINER.md). Please do not post security vulnerabilities to the public issue tracker.
29 changes: 27 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,25 @@ instruments = [
"opentelemetry-instrumentation >= 0.41b0",
"opentelemetry-instrumentation-fastapi >= 0.41b0",
"opentelemetry-instrumentation-requests >= 0.41b0",
"opentelemetry-instrumentation-httpx >= 0.41b0",
"opentelemetry-instrumentation-flask >= 0.41b0",
"opentelemetry-instrumentation-django >= 0.41b0",
"opentelemetry-instrumentation-urllib3 >= 0.41b0",
"opentelemetry-instrumentation-starlette >= 0.41b0",
"opentelemetry-instrumentation-sqlalchemy >= 0.41b0",
"opentelemetry-instrumentation-redis >= 0.41b0",
"opentelemetry-instrumentation-celery >= 0.41b0",
"opentelemetry-instrumentation-grpc >= 0.41b0",
"opentelemetry-instrumentation-logging >= 0.41b0",
]

# GenAI / AI model auto-instrumentation
genai = [
"opentelemetry-instrumentation-openai-v2 >= 2.0b0",
"opentelemetry-instrumentation-anthropic >= 0.1b0",
"opentelemetry-instrumentation-vertexai >= 0.1b0",
"opentelemetry-instrumentation-google-genai >= 0.1b0",
"opentelemetry-instrumentation-langchain >= 0.1b0",
]

# Cross-service carrier propagation (SQS, Kafka, Celery, Redis)
Expand All @@ -84,7 +101,7 @@ carriers = [

# Everything
all = [
"botanu[sdk,instruments,carriers]",
"botanu[sdk,instruments,genai,carriers]",
]

# Development / CI
Expand Down Expand Up @@ -138,7 +155,13 @@ select = [
ignore = [
"E501", # line too long — handled by formatter
"S101", # assert in tests is fine
"S110", # try-except-pass is intentional in resource detection
"UP006", # dict vs Dict — keep Dict[] for 3.9 compat
"UP007", # X | Y syntax — keep Optional[] for 3.9 compat
"UP035", # typing.Dict deprecated — keep for 3.9 compat
"UP045", # X | None vs Optional — keep Optional[] for 3.9 compat
"RUF002", # ambiguous dash — intentional in docstrings
"RUF022", # __all__ not sorted — grouped logically
]

[tool.ruff.lint.per-file-ignores]
Expand All @@ -154,10 +177,12 @@ line-ending = "auto"
# ---------------------------------------------------------------------------
[tool.mypy]
python_version = "3.9"
warn_return_any = true
warn_return_any = false
warn_unused_configs = true
ignore_missing_imports = true
strict = false
# OTel SDK types are not always precise; runtime behavior is correct
disable_error_code = ["arg-type", "attr-defined", "operator", "misc"]

# ---------------------------------------------------------------------------
# pytest
Expand Down
76 changes: 76 additions & 0 deletions src/botanu/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# SPDX-FileCopyrightText: 2026 The Botanu Authors
# SPDX-License-Identifier: Apache-2.0

"""Botanu SDK - OpenTelemetry-native cost attribution for AI workflows.

Quick Start::

from botanu import enable, botanu_use_case, emit_outcome

enable(service_name="my-app")

@botanu_use_case(name="Customer Support")
async def handle_request(data):
result = await process(data)
emit_outcome("success", value_type="tickets_resolved", value_amount=1)
return result
"""

from __future__ import annotations

from botanu._version import __version__

# Run context model
from botanu.models.run_context import RunContext, RunOutcome, RunStatus

# Bootstrap
from botanu.sdk.bootstrap import (
disable,
enable,
is_enabled,
)

# Configuration
from botanu.sdk.config import BotanuConfig

# Context helpers (core — no SDK dependency)
from botanu.sdk.context import (
get_baggage,
get_current_span,
get_run_id,
get_use_case,
set_baggage,
)

# Decorators (primary integration point)
from botanu.sdk.decorators import botanu_outcome, botanu_use_case, use_case

# Span helpers
from botanu.sdk.span_helpers import emit_outcome, set_business_context

__all__ = [
"__version__",
# Bootstrap
"enable",
"disable",
"is_enabled",
# Configuration
"BotanuConfig",
# Decorators
"botanu_use_case",
"use_case",
"botanu_outcome",
# Span helpers
"emit_outcome",
"set_business_context",
"get_current_span",
# Context
"get_run_id",
"get_use_case",
"set_baggage",
"get_baggage",
# Run context
"RunContext",
"RunStatus",
"RunOutcome",
]
13 changes: 13 additions & 0 deletions src/botanu/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2026 The Botanu Authors
# SPDX-License-Identifier: Apache-2.0

"""Dynamic version from package metadata (set by hatch-vcs at build time)."""

from __future__ import annotations

try:
from importlib.metadata import version

__version__: str = version("botanu")
except Exception:
__version__ = "0.0.0.dev0"
10 changes: 10 additions & 0 deletions src/botanu/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: 2026 The Botanu Authors
# SPDX-License-Identifier: Apache-2.0

"""Botanu data models."""

from __future__ import annotations

from botanu.models.run_context import RunContext, RunOutcome, RunStatus

__all__ = ["RunContext", "RunOutcome", "RunStatus"]
Loading
Loading