1+ from flask import Flask , jsonify , request
2+ import traceback
3+ import logging
4+ from functools import wraps
5+ from opentelemetry import trace , metrics
6+ from opentelemetry .trace .status import StatusCode
7+
8+
9+ from middleware import MwTracker
10+ tracker = MwTracker ()
11+
12+ # Initialize Flask app
13+ app = Flask (__name__ )
14+
15+ # Trace provider
16+ tracer = trace .get_tracer ("custom-tracer" )
17+
18+ # Metric provider
19+ meter = metrics .get_meter ("custom-meter" )
20+
21+ # Setup Python logging
22+ logging .basicConfig (level = logging .INFO )
23+ logger = logging .getLogger (__name__ )
24+
25+ # Custom Metrics: Counter
26+ request_counter = meter .create_counter (
27+ name = "requests_total" ,
28+ description = "Total number of requests" ,
29+ unit = "1"
30+ )
31+
32+ # Custom Traces: Tracing decorator with error handling
33+ def trace_request (func ):
34+ @wraps (func ) # Preserve the original function's name and docstring
35+ def wrapper (* args , ** kwargs ):
36+ with tracer .start_as_current_span (func .__name__ ) as span :
37+ span .set_attribute ("custom.attribute" , "example_value" )
38+
39+ # Log the trace and span IDs
40+ span_context = span .get_span_context ()
41+ logger .info (f"Start processing { func .__name__ } : trace_id={ span_context .trace_id } , span_id={ span_context .span_id } " )
42+
43+ try :
44+ result = func (* args , ** kwargs )
45+
46+ # Only check status code for POST request handling
47+ if request .method == 'POST' :
48+ if result .status_code >= 400 :
49+ span .set_status (StatusCode .ERROR )
50+ logger .error (f"Error occurred in { func .__name__ } : status_code={ result .status_code } " )
51+
52+ return result
53+
54+ except Exception as e :
55+ span .set_status (StatusCode .ERROR )
56+ span .record_exception (e )
57+ logger .error (f"Exception occurred in { func .__name__ } : { str (e )} " )
58+ logger .error (f"Stack Trace:\n { traceback .format_exc ()} " ) # Log the full stack trace
59+ return jsonify ({"error" : "An internal error occurred" }), 500
60+ return wrapper
61+
62+ @app .route ('/' )
63+ @trace_request
64+ def home ():
65+ request_counter .add (1 , {"endpoint" : "home" })
66+ logger .info ("Home endpoint accessed" )
67+ return jsonify ({"message" : "Welcome to the Flask app!" })
68+
69+ @app .route ('/process' , methods = ['GET' , 'POST' ])
70+ @trace_request
71+ def process_data ():
72+ if request .method == 'GET' :
73+ # Render a simple HTML form for demonstration
74+ return '''
75+ <form method="POST">
76+ <label for="data">Enter some data (JSON format):</label><br>
77+ <textarea id="data" name="data" rows="4" cols="50"></textarea><br>
78+ <input type="submit" value="Submit">
79+ </form>
80+ '''
81+
82+ if request .method == 'POST' :
83+ # Process JSON data submitted via the form
84+ try :
85+ data = request .json if request .is_json else request .form .get ('data' )
86+ request_counter .add (1 , {"endpoint" : "process" })
87+ logger .info (f"Processing data: { data } " )
88+
89+ with tracer .start_as_current_span ("data_processing" ) as span :
90+ span .set_attribute ("request.data" , str (data ))
91+ # Simulate processing
92+ processed_data = {"processed" : data }
93+ logger .info ("Data processed successfully" )
94+
95+ response = jsonify (processed_data ) # Create response object
96+
97+ return response # Return the response object
98+
99+ except Exception as e :
100+ span .set_status (StatusCode .ERROR )
101+ span .record_exception (e )
102+ logger .error (f"Exception occurred in process_data: { str (e )} " )
103+ logger .error (f"Stack Trace:\n { traceback .format_exc ()} " )
104+ return jsonify ({"error" : "An internal error occurred" }), 500
105+
106+ @app .route ('/error' )
107+ @trace_request
108+ def error ():
109+ request_counter .add (1 , {"endpoint" : "error" })
110+ logger .warning ("Error endpoint accessed, simulating an error" )
111+
112+ # Simulate an exception to trigger stack trace logging
113+ raise ValueError ("Simulated internal server error" )
114+
115+ if __name__ == '__main__' :
116+ app .run (port = 5000 )
0 commit comments