NirikshaAI Python SDK — full-stack observability via OpenTelemetry
Project description
NirikshaAI Python SDK
The official Python SDK for NirikshaAI — AI-native observability for logs, metrics, traces, and LLM/agent telemetry.
Under the hood this is a thin wrapper around the OpenTelemetry Python SDK. It configures OTLP exporters, wires up auto-instrumentation, and exposes NirikshaAI-specific helpers (evals, prompt management). You can use the standard OTEL API at any time alongside it.
Table of Contents
- Installation
- Quick Start
- LLM Applications
- Configuration Reference
- Auto-Instrumented Libraries
- Using the Standard OTEL API
- Logging Integration
- Eval Submission
- Prompt Management
- Framework Examples
- Environment Variables
Installation
pip install nirikshaai
To include automatic instrumentation for common web frameworks and infrastructure libraries (Django, Flask, FastAPI, SQLAlchemy, Redis, etc.):
pip install "nirikshaai[all]"
To also include automatic instrumentation for LLM libraries (OpenAI, Anthropic, LangChain, etc.):
pip install "nirikshaai[all,llm]"
Minimum Python version: 3.9
Quick Start
Two lines is all it takes to start sending traces, metrics, and logs to NirikshaAI from any Python service:
import nirikshaai
nirikshaai.init(
endpoint="https://app.niriksha.ai",
otlp_endpoint="grpc-ingest.niriksha.ai:443", # SaaS: OTLP gateway is separate from the REST API
api_key="nai_...",
service_name="my-service",
)
# That's it — traces, metrics, and logs now flow to NirikshaAI
Your api_key is a project-scoped key (prefixed nai_). It encodes which org and project your telemetry belongs to — you do not need to pass org or project IDs separately.
LLM Applications
Enable LLM instrumentation with the enable_llm flag. When set, the SDK automatically patches supported LLM client libraries so that every API call creates a standard OpenTelemetry span with token counts, model name, and (optionally) prompt/completion content.
import nirikshaai
nirikshaai.init(
endpoint="https://app.niriksha.ai",
api_key="nai_...",
service_name="my-ai-service",
enable_llm=True, # Auto-instruments OpenAI, Anthropic, LangChain, etc.
capture_prompts=False, # Set True only if PII controls are in place
)
import openai # auto-instrumented — every call creates an OTEL span
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Summarise this document."}],
)
# A LLM span is emitted automatically — no extra code needed
Privacy note:
capture_prompts=Falseis the default. Setting it toTruewill capture the full text of prompts and completions as span attributes (llm.input.messages/llm.output.messages). Only enable this if you have appropriate data governance and PII controls in place.
Configuration Reference
All parameters are passed to nirikshaai.init().
| Parameter | Type | Default | Description |
|---|---|---|---|
endpoint |
str |
(required) | NirikshaAI REST/control-plane base URL. SaaS: https://app.niriksha.ai. Private Cloud: https://niriksha.internal |
api_key |
str |
(required) | Project-scoped API key with nai_ prefix |
service_name |
str |
"my-service" |
Value of the service.name OTEL resource attribute |
environment |
str |
"production" |
Value of the deployment.environment OTEL resource attribute |
enable_metrics |
bool |
True |
Export OTLP metrics on a 60-second periodic interval |
enable_logs |
bool |
True |
Attach an OTLP log handler to the root Python logging logger |
enable_llm |
bool |
False |
Auto-instrument supported LLM client libraries (opt-in) |
capture_prompts |
bool |
False |
Capture llm.input/output.messages span attributes (PII risk) |
otlp_port |
int |
4317 |
OTLP gRPC port. Ignored when otlp_endpoint is set. |
otlp_endpoint |
str |
None |
Override the gRPC OTLP address (host:port, no scheme). SaaS: grpc-ingest.niriksha.ai:443 |
insecure |
bool |
False |
Send gRPC without TLS. Use when TLS is terminated at an ingress. |
tls_skip_verify |
bool |
False |
Use TLS but skip server certificate validation. Dev/staging only. |
ca_cert_file |
str |
None |
Path to a PEM CA certificate for verifying the gateway TLS cert. |
disable_instrumentations |
list[str] |
[] |
Library names to skip during auto-instrumentation (e.g. ["django"]) |
Private Cloud examples
# TLS with trusted certificate (system roots)
nirikshaai.init(
endpoint="https://niriksha.internal",
otlp_endpoint="niriksha.internal:4317",
api_key="nai_...",
)
# Custom / self-signed CA
nirikshaai.init(
endpoint="https://niriksha.internal",
otlp_endpoint="niriksha.internal:4317",
api_key="nai_...",
ca_cert_file="/etc/ssl/niriksha-ca.crt",
)
# Skip TLS verification (dev/staging only)
nirikshaai.init(
endpoint="https://niriksha.internal",
otlp_endpoint="niriksha.internal:4317",
api_key="nai_...",
tls_skip_verify=True,
)
# Plaintext gRPC (TLS terminated at ingress)
nirikshaai.init(
endpoint="https://niriksha.internal",
otlp_endpoint="niriksha.internal:4317",
api_key="nai_...",
insecure=True,
)
Auto-Instrumented Libraries
General (always enabled when the package is installed)
| Library | What's captured |
|---|---|
django |
HTTP requests and responses, middleware timing, view names |
flask |
Routes, request timing, status codes |
fastapi |
Routes, request timing, async support, response codes |
starlette |
Routes, middleware, ASGI lifecycle |
requests |
Outbound HTTP calls, method, URL, status code |
urllib3 |
Low-level HTTP connections and retries |
aiohttp |
Async HTTP client calls |
grpc |
gRPC server and client calls, method names |
sqlalchemy |
SQL queries and transaction timing (values are not captured) |
psycopg2 |
PostgreSQL query timing and operation type |
asyncpg |
Async PostgreSQL query timing |
pymongo |
MongoDB operation type, collection, database |
redis |
Redis command name (values are not captured) |
celery |
Task name, queue, execution state, retry count |
LLM (requires enable_llm=True)
| Library | What's captured |
|---|---|
openai |
Chat completions, embeddings, model name, token usage (prompt + completion) |
anthropic |
Messages API calls, model name, token usage |
langchain |
Chain invocations, individual tool call spans, retrieval steps |
llama_index |
Query engine spans, retrieval spans, synthesiser spans |
mistralai |
Chat completions, model name, token usage |
google-generativeai |
Gemini API calls, model name, token usage |
Using the Standard OTEL API
nirikshaai.init() configures the global OpenTelemetry providers. You can use the standard OTEL API directly at any point after calling init():
from opentelemetry import trace, metrics
tracer = trace.get_tracer("my-service")
meter = metrics.get_meter("my-service")
# Custom span
with tracer.start_as_current_span("process-order") as span:
span.set_attribute("order.id", order_id)
span.set_attribute("order.total", total)
span.set_attribute("order.currency", "USD")
result = fulfil_order(order_id)
span.set_attribute("order.status", result.status)
# Custom counter
order_counter = meter.create_counter(
"orders.processed",
description="Number of orders processed",
unit="{order}",
)
order_counter.add(1, {"status": "success", "region": "us-east"})
# Custom histogram (useful for latency)
latency_histogram = meter.create_histogram(
"order.processing.duration",
description="Time to process an order",
unit="ms",
)
latency_histogram.record(142.5, {"order_type": "express"})
Logging Integration
When enable_logs=True (the default), the SDK attaches an OTLP log handler to Python's root logger. All log records emitted through the standard logging module are automatically exported to NirikshaAI, with trace and span IDs attached so log lines are correlated to their parent trace.
import logging
logger = logging.getLogger("my-service")
# Structured extra fields are forwarded as log record attributes
logger.info("Order processed", extra={"order_id": "abc123", "amount": 99.99})
logger.warning("Inventory low", extra={"sku": "WIDGET-001", "remaining": 3})
logger.error("Payment failed", extra={"error_code": "CARD_DECLINED", "order_id": "abc123"})
# Exception info is captured automatically
try:
process_payment(order)
except PaymentError as exc:
logger.exception("Unhandled payment error", extra={"order_id": order.id})
Logs are exported in batches over OTLP gRPC to the same endpoint as traces and metrics.
Eval Submission
Submit evaluation results for LLM responses. Evals are linked to a specific trace so results appear in the NirikshaAI LLM Traces view alongside the originating span.
Single eval
import nirikshaai
nirikshaai.submit_eval(
trace_id="your-otel-trace-id", # hex trace ID from the OTEL span context
metric_name="faithfulness",
score=0.92, # float in [0, 1]
label="pass", # "pass" | "fail" | any custom label
explanation="Response accurately reflects the source documents",
eval_type="llm_judge", # "llm_judge" | "rule_based" | "human"
)
Batch eval
nirikshaai.submit_evals_batch([
{
"trace_id": "abc123...",
"metric_name": "toxicity",
"score": 0.02,
"label": "pass",
"eval_type": "rule_based",
},
{
"trace_id": "abc123...",
"metric_name": "relevance",
"score": 0.87,
"label": "pass",
"eval_type": "llm_judge",
"explanation": "Response addresses the user's question directly",
},
])
Obtaining the trace ID from an active span
from opentelemetry import trace
with tracer.start_as_current_span("llm-call") as span:
ctx = span.get_span_context()
trace_id = format(ctx.trace_id, "032x") # 32-character hex string
response = client.chat.completions.create(...)
# Submit eval referencing this trace
nirikshaai.submit_eval(
trace_id=trace_id,
metric_name="faithfulness",
score=judge(response),
label="pass",
)
Prompt Management
Fetch versioned prompt templates from the NirikshaAI prompt vault. Variable substitution is performed server-side before the rendered text is returned.
Fetch the latest deployed version
prompt = nirikshaai.get_prompt("customer-support-system")
print(prompt["text"]) # Rendered prompt text
print(prompt["version"]) # Active version number
print(prompt["name"])
Fetch a specific version with variable substitution
prompt = nirikshaai.get_prompt(
"product-description",
version=3,
variables={
"product_name": "Widget Pro",
"category": "Electronics",
"price": "$49.99",
},
)
print(prompt["text"]) # All {{variables}} replaced server-side
List all available prompts
prompts = nirikshaai.list_prompts()
for p in prompts:
print(f"{p['name']} (v{p['version']}) — {p['description']}")
Framework Examples
Django
Call nirikshaai.init() in your settings.py (or in an AppConfig.ready() method). Auto-instrumentation is applied globally once at startup.
# myproject/settings.py
import nirikshaai
nirikshaai.init(
endpoint="https://app.niriksha.ai",
api_key="nai_...",
service_name="django-app",
environment="production",
)
INSTALLED_APPS = [
# ... your apps
]
Flask
from flask import Flask
import nirikshaai
# init() before creating the Flask app
nirikshaai.init(
endpoint="https://app.niriksha.ai",
api_key="nai_...",
service_name="flask-app",
)
app = Flask(__name__)
@app.route("/orders/<order_id>")
def get_order(order_id):
# This route is automatically traced — no extra code needed
order = db.get_order(order_id)
return {"id": order_id, "status": order.status}
FastAPI
from fastapi import FastAPI
import nirikshaai
nirikshaai.init(
endpoint="https://app.niriksha.ai",
api_key="nai_...",
service_name="fastapi-app",
)
app = FastAPI()
@app.get("/orders/{order_id}")
async def get_order(order_id: str):
# Async routes are fully supported — traced automatically
order = await db.get_order(order_id)
return {"id": order_id, "status": order.status}
Celery
from celery import Celery
import nirikshaai
nirikshaai.init(
endpoint="https://app.niriksha.ai",
api_key="nai_...",
service_name="celery-worker",
)
app = Celery("tasks", broker="redis://localhost:6379/0")
@app.task
def send_notification(user_id: str, message: str):
# Every task invocation is automatically traced
# The task name, queue, and retry count appear as span attributes
notify(user_id, message)
LLM application with eval feedback loop
import nirikshaai
from opentelemetry import trace
nirikshaai.init(
endpoint="https://app.niriksha.ai",
api_key="nai_...",
service_name="rag-service",
enable_llm=True,
)
import openai
client = openai.OpenAI()
tracer = trace.get_tracer("rag-service")
def answer_question(question: str) -> str:
with tracer.start_as_current_span("answer-question") as span:
span.set_attribute("question.length", len(question))
# LLM call is auto-instrumented — a child span is created
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": question},
],
)
answer = response.choices[0].message.content
# Record trace ID for eval submission
ctx = span.get_span_context()
trace_id = format(ctx.trace_id, "032x")
# Async eval — run your judge independently and post the result
score = run_faithfulness_judge(question, answer)
nirikshaai.submit_eval(
trace_id=trace_id,
metric_name="faithfulness",
score=score,
label="pass" if score >= 0.8 else "fail",
eval_type="llm_judge",
)
return answer
Environment Variables
You can configure the SDK through standard OpenTelemetry environment variables instead of (or in addition to) passing arguments to init(). Environment variables take lower precedence than explicit arguments.
| Variable | Equivalent init() parameter |
|---|---|
OTEL_SERVICE_NAME |
service_name |
OTEL_EXPORTER_OTLP_ENDPOINT |
Derived from endpoint + otlp_port |
OTEL_EXPORTER_OTLP_HEADERS |
Set to X-API-Key=nai_your_key |
OTEL_RESOURCE_ATTRIBUTES |
Use to set deployment.environment and other attributes |
Example shell setup:
export OTEL_SERVICE_NAME=my-service
export OTEL_EXPORTER_OTLP_ENDPOINT=http://your-nirikshaai:4317
export OTEL_EXPORTER_OTLP_HEADERS="X-API-Key=nai_your_key"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production"
Then call init() with no arguments (the SDK will read the environment):
import nirikshaai
nirikshaai.init()
License
Apache 2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nirikshaai-0.0.1.dev5.tar.gz.
File metadata
- Download URL: nirikshaai-0.0.1.dev5.tar.gz
- Upload date:
- Size: 26.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d72d9c409162108ca0f928547fa7eb6dda5eeaf869043f7ed2813fb9de950c0b
|
|
| MD5 |
3e22b1aff387232f7ffaf9d25bbfb3d7
|
|
| BLAKE2b-256 |
0005ee4cc2fd1bb8c12629dea58c170a8d5ccc697d40021f00900f830e72729d
|
Provenance
The following attestation bundles were made for nirikshaai-0.0.1.dev5.tar.gz:
Publisher:
dev-release.yml on san-data-systems/niriksha-sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nirikshaai-0.0.1.dev5.tar.gz -
Subject digest:
d72d9c409162108ca0f928547fa7eb6dda5eeaf869043f7ed2813fb9de950c0b - Sigstore transparency entry: 1639218453
- Sigstore integration time:
-
Permalink:
san-data-systems/niriksha-sdk-python@8000e7a6305332e76042fb5a37495a3b7861d5a6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/san-data-systems
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
dev-release.yml@8000e7a6305332e76042fb5a37495a3b7861d5a6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file nirikshaai-0.0.1.dev5-py3-none-any.whl.
File metadata
- Download URL: nirikshaai-0.0.1.dev5-py3-none-any.whl
- Upload date:
- Size: 21.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe51fee3cefd2802397b523ccf81a2ee2a847aa5d06a4cd5ef61f53643fc56bc
|
|
| MD5 |
ed1b2112a8700af839a656b29bc9de0d
|
|
| BLAKE2b-256 |
27d55024fa7665709c50d1a2e196216af95d42dc600188812f65620ac0b4febd
|
Provenance
The following attestation bundles were made for nirikshaai-0.0.1.dev5-py3-none-any.whl:
Publisher:
dev-release.yml on san-data-systems/niriksha-sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nirikshaai-0.0.1.dev5-py3-none-any.whl -
Subject digest:
fe51fee3cefd2802397b523ccf81a2ee2a847aa5d06a4cd5ef61f53643fc56bc - Sigstore transparency entry: 1639218585
- Sigstore integration time:
-
Permalink:
san-data-systems/niriksha-sdk-python@8000e7a6305332e76042fb5a37495a3b7861d5a6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/san-data-systems
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
dev-release.yml@8000e7a6305332e76042fb5a37495a3b7861d5a6 -
Trigger Event:
push
-
Statement type: