Skip to content

Commit f4234eb

Browse files
solonkoolesyaOlesia Solonko
andauthored
Refactor App insight integration (#39)
* Add Application Insight integration * Add Application Insight integration * Refactor Application Insight integration --------- Co-authored-by: Olesia Solonko <[email protected]>
1 parent 8aca70f commit f4234eb

File tree

5 files changed

+63
-44
lines changed

5 files changed

+63
-44
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ PYTHON ?= python3
77
# ----- Container images -----
88
FRONTEND_IMAGE_LOCAL := local/global-tsunami-risk-map-frontend:latest
99
FRONTEND_IMAGE_REMOTE := ghcr.io/yejiyang/global-tsunami-risk-map-frontend:latest
10-
BACKEND_IMAGE_LOCAL := geopython/pygeoapi:latest
10+
BACKEND_IMAGE_LOCAL := geopython-api:latest
1111
BACKEND_IMAGE_REMOTE := ghcr.io/yejiyang/pygeoapi-w-global-tsunami-data:latest
1212

1313
# Utility containers for data processing (avoid local installs)

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ services:
2727

2828
# Local development services
2929
backend-local:
30-
image: geopython/pygeoapi:latest
30+
image: geopython-api:latest
3131
container_name: backend
3232
ports:
3333
- "5000:5000"
@@ -41,7 +41,7 @@ services:
4141
- CONTAINER_HOST=0.0.0.0
4242
- CONTAINER_PORT=5000
4343
- PYGEOAPI_SERVER_URL=http://localhost:5000
44-
- APPLICATIONINSIGHTS_CONNECTION_STRING=""
44+
#- APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=b4d987bc-1712-4026-aafb-f590fd854ab3;IngestionEndpoint=https://norwayeast-0.in.applicationinsights.azure.com/;LiveEndpoint=https://norwayeast.livediagnostics.monitor.azure.com/;ApplicationId=9fc4692c-7609-4abb-b547-49203ac14d4a
4545
profiles:
4646
- local
4747

frontend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:24-alpine as build
1+
FROM node:24-alpine AS build
22
WORKDIR /app
33
COPY package.json package-lock.json ./
44
COPY build.js ./
Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
# appinsights_init.py - Lightweight Application Insights setup for pygeoapi
2+
23
import os
34
import logging
45
from opencensus.ext.azure.log_exporter import AzureLogHandler
56
from opencensus.ext.azure.trace_exporter import AzureExporter
67
from opencensus.ext.flask.flask_middleware import FlaskMiddleware
78
from opencensus.trace.samplers import ProbabilitySampler
89

10+
# Global logger for reuse
11+
_insights_logger = None
12+
913

1014
def setup_app_insights(app):
1115
"""
1216
Setup lightweight Application Insights for pygeoapi
13-
Only tracks user interactions and basic telemetry
17+
Tracks user interactions and basic telemetry
1418
"""
1519
connection_string = os.environ.get('APPLICATIONINSIGHTS_CONNECTION_STRING')
1620

@@ -19,19 +23,29 @@ def setup_app_insights(app):
1923
return
2024

2125
try:
22-
# Setup request tracking with low sampling rate for lightweight monitoring
26+
print("[appinsights] Setting up Application Insights with connection string")
27+
28+
# Initialize OpenCensus Flask middleware
2329
middleware = FlaskMiddleware(
2430
app,
2531
exporter=AzureExporter(connection_string=connection_string),
26-
sampler=ProbabilitySampler(rate=0.1) # Sample 10% of requests for lightweight monitoring
32+
sampler=ProbabilitySampler(rate=0.1) # Sample 10% of requests
2733
)
2834

29-
# Setup basic logging for user interactions
30-
logger = logging.getLogger(__name__)
31-
logger.addHandler(AzureLogHandler(connection_string=connection_string))
35+
# Setup base logging
36+
logging.basicConfig(level=logging.INFO)
37+
logger = logging.getLogger('pygeoapi_insights')
38+
39+
if not any(isinstance(h, AzureLogHandler) for h in logger.handlers):
40+
handler = AzureLogHandler(connection_string=connection_string)
41+
logger.addHandler(handler)
42+
3243
logger.setLevel(logging.INFO)
3344

34-
# Add custom properties for better analytics
45+
global _insights_logger
46+
_insights_logger = logger # Store globally for reuse in log_user_interaction
47+
48+
# Add request attributes to spans
3549
@app.before_request
3650
def before_request():
3751
from flask import request
@@ -41,27 +55,31 @@ def before_request():
4155
if tracer:
4256
span = tracer.current_span()
4357
if span:
44-
# Add custom properties for analytics
4558
span.add_attribute('user_agent', request.headers.get('User-Agent', ''))
4659
span.add_attribute('referrer', request.headers.get('Referer', ''))
4760
span.add_attribute('api_endpoint', request.endpoint or 'unknown')
4861

49-
print("Application Insights configured successfully")
62+
print("[appinsights] Application Insights configured successfully")
5063

5164
except Exception as e:
52-
print(f"Failed to setup Application Insights: {e}")
65+
print(f"[appinsights] Failed to setup Application Insights: {e}")
66+
import traceback
67+
traceback.print_exc()
5368

5469

55-
# Custom logging function for user interФactions
5670
def log_user_interaction(action, details=None):
57-
"""Log user interactions for analytics"""
58-
connection_string = os.environ.get('APPLICATIONINSIGHTS_CONNECTION_STRING')
59-
if connection_string:
60-
logger = logging.getLogger('user_analytics')
61-
logger.addHandler(AzureLogHandler(connection_string=connection_string))
71+
"""
72+
Log user interactions for analytics
73+
"""
74+
if _insights_logger is None:
75+
print("[appinsights] Telemetry not initialized, skipping interaction log")
76+
return
6277

63-
log_data = {'action': action}
64-
if details:
65-
log_data.update(details)
78+
log_data = {'action': action}
79+
if details:
80+
log_data.update(details)
6681

67-
logger.info(f"User interaction: {action}", extra={'custom_dimensions': log_data})
82+
_insights_logger.info(
83+
f"User interaction: {action}",
84+
extra={'custom_dimensions': log_data}
85+
)

pygeoapi/docker/init.sh

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,47 +62,48 @@ if [ -n "$APPLICATIONINSIGHTS_CONNECTION_STRING" ]; then
6262

6363
# Create a startup script that integrates Application Insights
6464
cat > /tmp/start_with_insights.py << 'EOF'
65-
import sys
6665
import os
66+
import sys
6767
68-
# Add the root directory to Python path to find appinsights_init
68+
# Add root to Python path to import appinsights_init
6969
sys.path.insert(0, '/')
7070
7171
try:
72-
# Import the Application Insights setup
7372
import appinsights_init
74-
print("[init] Application Insights module loaded successfully")
73+
print("[start_with_insights] Application Insights module loaded")
7574
76-
# Import pygeoapi app
75+
# Import prebuilt Flask app instance
7776
from pygeoapi.flask_app import APP as app
77+
print("[start_with_insights] Flask app imported successfully")
7878
79-
# Setup Application Insights
79+
# Setup Application Insights telemetry
8080
appinsights_init.setup_app_insights(app)
81-
print("[init] Application Insights integrated successfully")
81+
print("[start_with_insights] Application Insights integrated")
8282
8383
except ImportError as e:
84-
print(f"[init] Application Insights setup skipped: {e}")
85-
# Continue without Application Insights
86-
pass
84+
print(f"[start_with_insights] ImportError: {e}")
85+
sys.exit(1)
86+
8787
except Exception as e:
88-
print(f"[init] Application Insights setup failed: {e}")
89-
# Continue without Application Insights
90-
pass
88+
print(f"[start_with_insights] Error during telemetry setup: {e}")
89+
import traceback
90+
traceback.print_exc()
91+
92+
# Run the app (development mode only)
93+
if __name__ == '__main__':
94+
print("[start_with_insights] Starting Flask app")
95+
app.run(host='0.0.0.0', port=5000)
9196
92-
print("[init] Application Insights setup completed")
9397
EOF
9498

9599
# Execute the Application Insights setup (but don't start the app yet)
96100
python3 /tmp/start_with_insights.py
97101

98102
else
99103
echo "$(get_timestamp) [init] Starting pygeoapi service without Application Insights"
100-
# Still need to generate OpenAPI document
101104
echo "$(get_timestamp) [init] Generating OpenAPI document"
102105
pygeoapi openapi generate /pygeoapi/local.config.yml --output-file /tmp/openapi.yml
106+
# Start the pygeoapi service
107+
echo "$(get_timestamp) [init] Starting pygeoapi service"
108+
exec /entrypoint.sh "$@"
103109
fi
104-
105-
106-
# Start the pygeoapi service
107-
echo "$(get_timestamp) [init] Starting pygeoapi service"
108-
exec /entrypoint.sh "$@"

0 commit comments

Comments
 (0)