FastHTML OpenTelemetry Streamer
Real-time OpenTelemetry streaming components for FastHTML applications. Stream telemetry data as beautiful, nested, collapsible components that update live as spans are created and completed.
Features
- One-line setup: Add real-time telemetry streaming with a single function call
- Beautiful UI: Collapsible, nested span visualization with status colors
- Real-time updates: See spans appear and update live via Server-Sent Events
- Thread-safe: Works seamlessly with any OpenTelemetry instrumentation
- Customizable: Bring your own renderers or extend the defaults
- AI-optimized: Specialized rendering for AI/LLM spans with rich metrics
- Attribute-based rendering: Custom renderers for specific span types
- Zero config: Sensible defaults, optional customization
Quick Start
from fasthtml.common import *
import fasthtml_otel as ft_otel
from opentelemetry.sdk.trace import TracerProvider
# Create your FastHTML app
app = FastHTML()
# Set up OpenTelemetry
provider = TracerProvider()
ft_otel.configure(app, provider)
# Your routes automatically get telemetry
@app.get("/")
def index():
return Div(
H1("My App"),
ft_otel.telemetry_container(),
)
serve()
That's it! Visit your app and you'll see live telemetry data streaming in.
Installation
pip install fasthtml-otel
Advanced Usage
Custom Container
import fasthtml_otel as ft_otel
from opentelemetry.sdk.trace import TracerProvider
# Configure with custom container ID and AI renderer
provider = TracerProvider()
ft_otel.configure(
app, provider,
container_id="my-telemetry",
attribute_renderers={
"gen_ai.operation.name": ft_otel.AISpanRenderer()
}
)
@app.get("/")
def index():
return Div(
H1("My App"),
ft_otel.telemetry_container(title="Custom Telemetry"),
)
Custom Renderers
import fasthtml_otel as ft_otel
from fasthtml_otel.renderers import SpanRenderer
from opentelemetry.sdk.trace import TracerProvider
class MySpanRenderer(SpanRenderer):
def render_header(self, span):
return Div(f"SPAN: {span.name}", cls="custom-header")
provider = TracerProvider()
ft_otel.configure(app, provider, renderer=MySpanRenderer())
Integration with Existing Telemetry
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
import fasthtml_otel as ft_otel
# Set up your existing OpenTelemetry
provider = TracerProvider()
# Don't set global provider yet - let ft_otel.configure() do it
# Add FastHTML streaming
ft_otel.configure(app, provider)
Example with Manual Tracing
from fasthtml.common import *
import fasthtml_otel as ft_otel
from opentelemetry.sdk.trace import TracerProvider
app = FastHTML()
provider = TracerProvider()
ft_otel.configure(app, provider)
# Get a tracer for manual instrumentation
tracer = provider.get_tracer("my-app")
@app.get("/")
def index():
return Div(
H1("Telemetry Demo"),
Button("Trigger Operation", hx_post="/process", hx_target="#result"),
Div(id="result"),
ft_otel.telemetry_container(),
)
@app.post("/process")
def process():
with tracer.start_as_current_span("user_operation") as span:
span.set_attribute("operation.type", "data_processing")
# Simulate some work with nested spans
with tracer.start_as_current_span("validate_data") as validate_span:
validate_span.set_attribute("data.size", 1024)
import time
time.sleep(0.1) # Simulate validation work
with tracer.start_as_current_span("process_data") as process_span:
process_span.set_attribute("algorithm", "example")
time.sleep(0.2) # Simulate processing work
span.set_attribute("success", True)
return Div("Operation completed! Check the telemetry panel.", cls="text-green-600")
Example with Pydantic AI
from fasthtml.common import *
import fasthtml_otel as ft_otel
from opentelemetry.sdk.trace import TracerProvider
from pydantic_ai import Agent
app = FastHTML()
provider = TracerProvider()
ft_otel.configure(
app, provider,
attribute_renderers={
"gen_ai.operation.name": ft_otel.AISpanRenderer(auto_expand_patterns=["chat", "Tool:"])
}
)
# Instrument Pydantic AI (renderer-agnostic)
ft_otel.instrument_pydantic_ai(provider)
agent = Agent("gpt-4o-mini")
@app.get("/")
def index():
return Div(
H1("Chat App"),
ft_otel.telemetry_container(),
)
@app.post("/chat")
def chat(msg: str):
result = agent.run(msg)
return Div(result.data)
Attribute-Based Custom Renderers
# Configure with attribute-based renderers
ft_otel.configure(
app, provider,
attribute_renderers={
"gen_ai.operation.name": ft_otel.AISpanRenderer(),
"db.operation": MyDatabaseRenderer(),
"http.method": HttpSpanRenderer()
}
)
# Or register individually after configuration
ft_otel.register_attribute_renderer("custom.span.type", CustomRenderer())
Development
git clone https://github.com/Novia-RDI-Seafaring/ft-otel
cd ft-otel
pip install -e ".[dev]"
# Run main example
cd example
python app.py
# Run AI-focused example
python ai_example.py --port 8003
Citation
If you use this software in your research or projects, please cite it as:
@software{fasthtml_otel,
title={FastHTML OpenTelemetry Streamer},
author={Christoffer Björkskog},
year={2025},
url={https://github.com/Novia-RDI-Seafaring/ft-otel}
}
Acknowledgments
This project is part of the Virtual Sea Trial Project (VST), funded by Business Finland.
License
MIT License - see LICENSE file for details.
Metadata
Release files for fasthtml-otel 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fasthtml_otel-0.1.1.tar.gz | 213.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fasthtml_otel-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 229.4 kB
Release files / fasthtml_otel-0.1.1.tar.gz
| Download URL | fasthtml_otel-0.1.1.tar.gz |
|---|---|
| Size | 213.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81503327826ae2c08b1dad6961af614bf9f4ec5b64363bb348615f19508498f4
|
|
BLAKE2b-256 checksum How to use checksums |
e1bf81aaf0549713619601e5ac6a2cc6ea2815d4c6c8223d5d7b1ff5e108f725
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.13
|
Release files / fasthtml_otel-0.1.1-py3-none-any.whl
| Download URL | fasthtml_otel-0.1.1-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a70fc612b881342bef867491ea311dd9e9d580af90da5cbdfec7de142eec623
|
|
BLAKE2b-256 checksum How to use checksums |
5abf88c6bc2f5df0d119d3af0590832037ebdaaab34867ef6fc6031609981f7e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.13
|
Security for fasthtml-otel 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.