|
|
|
|
@ -36,6 +36,31 @@ from configs import dify_config
|
|
|
|
|
from dify_app import DifyApp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ExceptionLoggingHandler(logging.Handler):
|
|
|
|
|
"""Custom logging handler that creates spans for logging.exception() calls"""
|
|
|
|
|
|
|
|
|
|
def emit(self, record):
|
|
|
|
|
try:
|
|
|
|
|
if record.exc_info:
|
|
|
|
|
tracer = get_tracer_provider().get_tracer("dify.exception.logging")
|
|
|
|
|
with tracer.start_as_current_span(
|
|
|
|
|
"log.exception",
|
|
|
|
|
attributes={
|
|
|
|
|
"log.level": record.levelname,
|
|
|
|
|
"log.message": record.getMessage(),
|
|
|
|
|
"log.logger": record.name,
|
|
|
|
|
"log.file.path": record.pathname,
|
|
|
|
|
"log.file.line": record.lineno,
|
|
|
|
|
},
|
|
|
|
|
) as span:
|
|
|
|
|
span.set_status(StatusCode.ERROR)
|
|
|
|
|
span.record_exception(record.exc_info[1])
|
|
|
|
|
span.set_attribute("exception.type", record.exc_info[0].__name__)
|
|
|
|
|
span.set_attribute("exception.message", str(record.exc_info[1]))
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@user_logged_in.connect
|
|
|
|
|
@user_loaded_from_request.connect
|
|
|
|
|
def on_user_loaded(_sender, user):
|
|
|
|
|
@ -103,6 +128,7 @@ def init_app(app: DifyApp):
|
|
|
|
|
if not is_celery_worker():
|
|
|
|
|
init_flask_instrumentor(app)
|
|
|
|
|
CeleryInstrumentor(tracer_provider=get_tracer_provider(), meter_provider=get_meter_provider()).instrument()
|
|
|
|
|
instrument_exception_logging()
|
|
|
|
|
init_sqlalchemy_instrumentor(app)
|
|
|
|
|
atexit.register(shutdown_tracer)
|
|
|
|
|
|
|
|
|
|
@ -111,6 +137,11 @@ def is_celery_worker():
|
|
|
|
|
return "celery" in sys.argv[0].lower()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def instrument_exception_logging():
|
|
|
|
|
exception_handler = ExceptionLoggingHandler()
|
|
|
|
|
logging.getLogger().addHandler(exception_handler)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_flask_instrumentor(app: DifyApp):
|
|
|
|
|
meter = get_meter("http_metrics", version=dify_config.CURRENT_VERSION)
|
|
|
|
|
_http_response_counter = meter.create_counter(
|
|
|
|
|
|