Metadata-Version: 2.4
Name: juntai-usage
Version: 1.0.0
Summary: Canonical Juntai usage events and OpenTelemetry reporting
Author: Juntai Platform Team
License-Expression: LicenseRef-Proprietary
Project-URL: Repository, https://github.com/zephytiju/JuntaiUsage
Project-URL: Documentation, https://github.com/zephytiju/JuntaiUsage#readme
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-api<2,>=1.35

# Juntai Usage

`juntai-usage` is the only producer library for canonical Juntai usage events.
It creates validated `juntai.usage/v1` records, derives retry-stable identifiers,
and emits dedicated OpenTelemetry log events through the application's configured
local SDK and Collector sidecar.

The package contains no database driver, service runtime, ingestion endpoint,
ledger, query, pricing, calculation, domain, or deployment code. Durable
acceptance remains the responsibility of JuntaiUsageCostService; a successful
local report means only that the configured OpenTelemetry SDK accepted the log
record.

## Producer example

```python
from datetime import UTC, datetime
from decimal import Decimal

from juntai.usage import (
    UsageContext,
    UsageEvent,
    UsageReporter,
    stable_usage_event_id,
)

source_id = "axiom-execution:exec-42:attempt-1:completed"
event = UsageEvent(
    event_id=stable_usage_event_id(
        producer_id="axiom.driver",
        source_id=source_id,
        meter="axiom.execution.cpu_time",
        part="total",
    ),
    context=UsageContext(
        tenant_id="tenant-7",
        service_namespace="juntai.axiom",
        service_name="driver",
        application_id="app-9",
        workflow_id="workflow-3",
        execution_id="exec-42",
    ),
    meter="axiom.execution.cpu_time",
    quantity=Decimal("18.250"),
    unit="s",
    occurred_at=datetime.now(UTC),
    source_id=source_id,
)

result = UsageReporter.from_otel().report(event)
if not result.enqueued:
    service_health.record_usage_reporting_failure(result.error_code)
```

Configure the process OpenTelemetry `LoggerProvider` with matching
`service.namespace` and `service.name` resource attributes and export OTLP over
HTTP/protobuf only to the local Collector sidecar. Re-reporting the same event is
safe because its identifier and encoded payload remain stable. Do not use a
timestamp or random value as `source_id`.

## Validation and meter definitions

`UsageEvent` accepts only `Decimal` quantities and normalizes them to a finite,
non-negative canonical string without exponent notation. Timestamps are
timezone-aware and normalized to UTC. `UsageMeter` can validate a locally known
published definition's accepted units and required application, workflow, or
execution attribution before emission. The service meter catalog remains the
authority.

The canonical JSON contract is
[`contracts/usage-event.v1.schema.json`](contracts/usage-event.v1.schema.json).
Deterministic valid and invalid fixtures are under [`fixtures`](fixtures).
Migration from the legacy Observability metric-window convention is documented
in [`docs/migration-from-observability.md`](docs/migration-from-observability.md).

## Local gates

```bash
uv sync --dev
uv run ruff format --check .
uv run ruff check .
uv run pytest
uv run python -m build
```

The integration suite uses the real OpenTelemetry SDK and in-memory exporter to
verify emitted log records and resource attribution. It deliberately does not
claim central Collector or ledger durability.
