open-telemetry / open-telemetry/opentelemetry-python
`opentelemetry` + `streamlit` = `Overriding of current TracerProvider is not allowed messages` and `Attempting to instrument while already instrumented`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 19
Description
Hello,
We have a Streamlit app in production and we are hoping to add observability to it by leveraging opentelemetry.instrumentation.logging.LoggingInstrumentor to integrate the current logging and OpenTelemetry to publish logs to Azure Monitor. I believe Streamlit executing the same piece of code more than once at runtime results in Overriding of current TracerProvider is not allowed messages, which in turn only publishes Attempting to instrument while already instrumented to Azure Monitor. I have tried to circumvent the issue the following few ways:
- Caching the logger and tracer via Streamlit's caching resources; to no avail, as doing so results in no logs being redirected to Azure. The below code snippet contains a minimal reproducible example of this: executing the example as is results in the what I describe above and uncommenting the caching decorator simply publishes nothing to Azure Monitor. (Execute the snippet by placing the snippet's content in
example.pyand runningstreamlit run example.py.) - Defining the logger and tracer in a different file, to ensure that piece of code is only executed once; which seems to not work either.
- I have though of trying
opentelemetry._logs, but the issue I'm hoping to describe seems to be intrinsic to how the OpenTelemetry Python SDK functions, so I don't think that would solve it either. Plus, that part of the API is experimental. - Fiddle around by pre-setting
opentelemetry.trace._TRACER_PROVIDERviaopentelemetry.trace.set_tracer_providerand related functions.
Please do let me know if this is not the place to ask such questions. I tried asking in the Streamlit forum but I have received no answers so far. Any help would be very much appreciated 😊
Thank you in advance,
Gorka.
import logging
import os
from pathlib import Path
import opentelemetry
import streamlit as st
import streamlit_authenticator as stauth
import yaml
from azure.monitor.opentelemetry import configure_azure_monitor
from dotenv import load_dotenv
from opentelemetry import trace
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from streamlit_calendar import calendar
from yaml.loader import SafeLoader
def user_config() -> tuple[str, bool, str, stauth.Authenticate]:
here = Path(__file__).parent
users_yaml_path = here / "src" / "frontend" / "users.yaml"
with open(users_yaml_path) as file:
config = yaml.load(file, Loader=SafeLoader)
authenticator = stauth.Authenticate(
config["credentials"],
config["cookie"]["name"],
config["cookie"]["key"],
config["cookie"]["expiry_days"],
config["preauthorized"],
)
name, authentication_status, username = authenticator.login("Login", "main")
return name, authentication_status, username, authenticator
def logged_in(authenticator: stauth.Authenticate, username: str) -> None:
with st.sidebar:
st.write(f'Welcome *{st.session_state["name"]}*')
vaults_markdown_list = "\n".join(
f"- {vault_name}"
for vault_name in authenticator.credentials["usernames"][username][
"vaults"
].split(";")
)
st.write(f"You have access to these vaults:\n{vaults_markdown_list}")
authenticator.logout("Logout", "main")
def not_logged_in() -> None:
if not st.session_state["authentication_status"]:
st.error("Username/password is incorrect")
st.markdown(
"""
<style>
section[data-testid="stSidebar"][aria-expanded="true"]{
display: none;
}
</style>
""",
unsafe_allow_html=True,
)
elif st.session_state["authentication_status"] is None:
st.warning("Please enter your username and password")
st.markdown(
"""
<style>
section[data-testid="stSidebar"][aria-expanded="true"]{
display: none;
}
</style>
""",
unsafe_allow_html=True,
)
# @st.cache_resource
def set_logger_and_tracer() -> tuple[logging.Logger, opentelemetry.trace.Tracer]:
configure_azure_monitor(
connection_string=os.environ["web_app_insights_connection_string"]
)
tracer = trace.get_tracer(__name__)
LoggingInstrumentor(set_logging_format=True, log_level=logging.INFO).instrument()
logger = logging.getLogger(__name__)
return logger, tracer
load_dotenv()
name, authentication_status, username, authenticator = user_config()
if st.session_state["authentication_status"]:
logger, tracer = set_logger_and_tracer()
with tracer.start_as_current_span("span_name"):
logger.info("Some logging")
logged_in(authenticator, username)
calendar_options = {
"headerToolbar": {
"left": "today prev,next",
"center": "title",
"right": "timeGridDay,timeGridWeek",
},
"slotMinTime": "00:00:00",
"slotMaxTime": "24:00:00",
"initialView": "timeGridWeek",
"selectable": True,
"selectMirror": True,
"editable": True,
}
custom_css = """
.fc-event-past {
opacity: 0.8;
}
.fc-event-time {
font-style: italic;
}
.fc-event-title {
font-weight: 700;
}
.fc-toolbar-title {
font-size: 2rem;
}
"""
new_event = calendar(
events=[],
options=calendar_options,
custom_css=custom_css,
callbacks=["dateClick", "eventChange", "eventClick", "eventsSet"],
)
else:
not_logged_in()
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the example in example.py with streamlit run example.py. Inspect configure_azure_monitor, LoggingInstrumentor.instrument(), and the calls to trace.set_tracer_provider while comparing Streamlit reruns. Done means identifying a supported initialization approach or a confirmed SDK change, with Azure Monitor receiving the expected logs without repeated instrumentation messages.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, python, streamlit
- Domain
- observability
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100