Skip to content

Commit 4e9c5ba

Browse files
committed
Add app insights and Logfire instrumentation
1 parent 617952c commit 4e9c5ba

File tree

5 files changed

+104
-3
lines changed

5 files changed

+104
-3
lines changed

infra/aca.bicep

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ param openAiEndpoint string
1212
param cosmosDbAccount string
1313
param cosmosDbDatabase string
1414
param cosmosDbContainer string
15+
param applicationInsightsConnectionString string = ''
1516

1617
resource acaIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
1718
name: identityName
@@ -58,6 +59,10 @@ module app 'core/host/container-app-upsert.bicep' = {
5859
name: 'AZURE_COSMOSDB_CONTAINER'
5960
value: cosmosDbContainer
6061
}
62+
{
63+
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
64+
value: applicationInsightsConnectionString
65+
}
6166
]
6267
targetPort: 8000
6368
}

infra/main.bicep

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0
155155
}
156156
}
157157

158+
// Application Insights for telemetry
159+
module applicationInsights 'br/public:avm/res/insights/component:0.4.2' = if (useMonitoring) {
160+
name: 'applicationinsights'
161+
scope: resourceGroup
162+
params: {
163+
name: '${prefix}-appinsights'
164+
location: location
165+
tags: tags
166+
workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId
167+
kind: 'web'
168+
applicationType: 'web'
169+
}
170+
}
171+
158172
// https://learn.microsoft.com/en-us/azure/container-apps/firewall-integration?tabs=consumption-only
159173
module containerAppsNSG 'br/public:avm/res/network/network-security-group:0.5.1' = if (useVnet) {
160174
name: 'containerAppsNSG'
@@ -669,6 +683,7 @@ module aca 'aca.bicep' = {
669683
cosmosDbAccount: cosmosDb.outputs.name
670684
cosmosDbDatabase: cosmosDbDatabaseName
671685
cosmosDbContainer: cosmosDbContainerName
686+
applicationInsightsConnectionString: useMonitoring ? applicationInsights.outputs.connectionString : ''
672687
exists: acaExists
673688
}
674689
}
@@ -738,3 +753,5 @@ output AZURE_COSMOSDB_ACCOUNT string = cosmosDb.outputs.name
738753
output AZURE_COSMOSDB_ENDPOINT string = cosmosDb.outputs.endpoint
739754
output AZURE_COSMOSDB_DATABASE string = cosmosDbDatabaseName
740755
output AZURE_COSMOSDB_CONTAINER string = cosmosDbContainerName
756+
757+
output APPLICATIONINSIGHTS_CONNECTION_STRING string = useMonitoring ? applicationInsights.outputs.connectionString : ''

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ dependencies = [
1616
"azure-ai-agents>=1.1.0",
1717
"agent-framework>=1.0.0b251016",
1818
"azure-cosmos>=4.9.0",
19+
"azure-monitor-opentelemetry>=1.6.4",
20+
"logfire>=3.11.0",
1921
]
2022

2123
[dependency-groups]

servers/deployed_mcp.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,49 @@
55
from enum import Enum
66
from typing import Annotated
77

8+
import logfire
89
from azure.cosmos.aio import CosmosClient
910
from azure.identity.aio import DefaultAzureCredential, ManagedIdentityCredential
11+
from azure.monitor.opentelemetry import configure_azure_monitor
12+
from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter
1013
from dotenv import load_dotenv
1114
from fastmcp import FastMCP
15+
from opentelemetry import trace
16+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
1217

13-
load_dotenv(override=True)
18+
RUNNING_IN_PRODUCTION = os.getenv("RUNNING_IN_PRODUCTION", "false").lower() == "true"
19+
20+
if not RUNNING_IN_PRODUCTION:
21+
load_dotenv(override=True)
1422

15-
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s")
23+
logging.basicConfig(level=logging.WARNING, format="%(asctime)s - %(message)s")
1624
logger = logging.getLogger("ExpensesMCP")
25+
logger.setLevel(logging.INFO)
26+
27+
# Configure OpenTelemetry tracing
28+
APPLICATIONINSIGHTS_CONNECTION_STRING = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING")
29+
if APPLICATIONINSIGHTS_CONNECTION_STRING:
30+
logger.info("Setting up Azure Monitor instrumentation")
31+
configure_azure_monitor()
32+
33+
# Use Logfire to instrument MCP tool calls
34+
logfire.configure(
35+
service_name="expenses-mcp",
36+
send_to_logfire=False, # Send spans to Application Insights, not Logfire backend
37+
)
38+
logfire.instrument_mcp()
39+
40+
if APPLICATIONINSIGHTS_CONNECTION_STRING:
41+
logger.info("Adding Azure Monitor Trace Exporter to TracerProvider")
42+
tracer_provider = trace.get_tracer_provider()
43+
exporter = AzureMonitorTraceExporter(connection_string=APPLICATIONINSIGHTS_CONNECTION_STRING)
44+
span_processor = BatchSpanProcessor(exporter)
45+
tracer_provider.add_span_processor(span_processor)
1746

1847
# Cosmos DB configuration from environment variables
1948
AZURE_COSMOSDB_ACCOUNT = os.environ["AZURE_COSMOSDB_ACCOUNT"]
2049
AZURE_COSMOSDB_DATABASE = os.environ["AZURE_COSMOSDB_DATABASE"]
2150
AZURE_COSMOSDB_CONTAINER = os.environ["AZURE_COSMOSDB_CONTAINER"]
22-
RUNNING_IN_PRODUCTION = os.getenv("RUNNING_IN_PRODUCTION", "false").lower() == "true"
2351
AZURE_CLIENT_ID = os.getenv("AZURE_CLIENT_ID", "")
2452

2553
# Configure Cosmos DB client and container

uv.lock

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)