|
10 | 10 | from flask.logging import default_handler
|
11 | 11 | from flask_login import LoginManager
|
12 | 12 | from flask_migrate import Migrate
|
| 13 | +from opentelemetry import trace |
| 14 | +from opentelemetry.exporter.jaeger.thrift import JaegerExporter |
| 15 | +from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter |
| 16 | +from opentelemetry.instrumentation.celery import CeleryInstrumentor |
| 17 | +from opentelemetry.instrumentation.flask import FlaskInstrumentor |
| 18 | +from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor |
| 19 | +from opentelemetry.instrumentation.requests import RequestsInstrumentor |
| 20 | +from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor |
| 21 | +from opentelemetry.sdk.resources import SERVICE_NAME, Resource |
| 22 | +from opentelemetry.sdk.trace import TracerProvider |
| 23 | +from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter |
13 | 24 | from sqlalchemy.exc import SQLAlchemyError
|
14 | 25 | from werkzeug.exceptions import InternalServerError, default_exceptions
|
15 | 26 |
|
@@ -133,10 +144,62 @@ def create_app(config_obj=None):
|
133 | 144 | app.register_error_handler(pydantic.ValidationError, validation_error)
|
134 | 145 |
|
135 | 146 | init_metrics(app)
|
136 |
| - |
| 147 | + _instrument_app(app) |
137 | 148 | return app
|
138 | 149 |
|
139 | 150 |
|
| 151 | +def _instrument_app(app): |
| 152 | + """ |
| 153 | + Instrument the Flask app. |
| 154 | +
|
| 155 | + Sets up the OpenTelemetry tracing exporter, configures the endpoint |
| 156 | + to send trace data to. |
| 157 | + """ |
| 158 | + # Some of the following has already been executed due to the manner in which |
| 159 | + # the tasks config is included.... |
| 160 | + |
| 161 | + service_name = "cachito-api" |
| 162 | + resource = Resource(attributes={SERVICE_NAME: service_name}) |
| 163 | + provider = TracerProvider(resource=resource) |
| 164 | + |
| 165 | + # Used for local development environment aka docker-compose up. |
| 166 | + if "CACHITO_JAEGER_EXPORTER_ENDPOINT" in app.config.keys(): |
| 167 | + app.logger.info("Configuring Jaeger Exporter") |
| 168 | + jaeger_exporter = JaegerExporter( |
| 169 | + agent_host_name=app.config["CACHITO_JAEGER_EXPORTER_ENDPOINT"], |
| 170 | + agent_port=int(app.config["CACHITO_JAEGER_EXPORTER_PORT"]), |
| 171 | + ) |
| 172 | + processor = BatchSpanProcessor(jaeger_exporter) |
| 173 | + # test/stage/prod environments.... |
| 174 | + elif "CACHITO_OTLP_EXPORTER_ENDPOINT" in app.config.keys(): |
| 175 | + app.logger.info( |
| 176 | + "Configuring OTLP Exporter: " + str(app.config["CACHITO_OTLP_EXPORTER_ENDPOINT"]) |
| 177 | + ) |
| 178 | + otlp_exporter = OTLPSpanExporter(endpoint=app.config["CACHITO_OTLP_EXPORTER_ENDPOINT"]) |
| 179 | + processor = BatchSpanProcessor(otlp_exporter) |
| 180 | + # Undefined; send data to the console. |
| 181 | + else: |
| 182 | + app.logger.info("Configuring ConsoleSpanExporter") |
| 183 | + processor = BatchSpanProcessor(ConsoleSpanExporter()) |
| 184 | + |
| 185 | + # Toggle between sending to jaeger and displaying span info on console |
| 186 | + provider.add_span_processor(processor) |
| 187 | + trace.set_tracer_provider(provider) |
| 188 | + |
| 189 | + FlaskInstrumentor().instrument_app( |
| 190 | + app, excluded_urls="/static/*,/favicon.ico,/metrics,/healthcheck" |
| 191 | + ) |
| 192 | + RequestsInstrumentor().instrument() |
| 193 | + CeleryInstrumentor().instrument() |
| 194 | + SQLAlchemyInstrumentor().instrument( |
| 195 | + enable_commenter=True, |
| 196 | + commenter_options={ |
| 197 | + "db_driver": True, |
| 198 | + }, |
| 199 | + ) |
| 200 | + Psycopg2Instrumentor().instrument(enable_commenter=True, commenter_options={}) |
| 201 | + |
| 202 | + |
140 | 203 | def create_cli_app():
|
141 | 204 | """
|
142 | 205 | Create a Flask application instance and validate the configuration for the Flask CLI.
|
|
0 commit comments