feat(ocr): observe ocr_processing_seconds around engine.to_thread calls
Wraps every asyncio.to_thread(engine.extract_*) call with time.monotonic() deltas in /ocr (per document) and in both /ocr/stream generators (per page). Streaming buckets are the useful operational signal; the non-streaming observation is a bonus. Refs #652 (AC5) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import zipfile
|
||||
from contextlib import asynccontextmanager
|
||||
from datetime import datetime, timezone
|
||||
@@ -108,6 +109,7 @@ async def run_ocr(request: OcrRequest):
|
||||
script_type = request.scriptType.upper()
|
||||
engine_name = "kraken" if script_type == "HANDWRITING_KURRENT" else "surya"
|
||||
|
||||
extract_started = time.monotonic()
|
||||
if script_type == "HANDWRITING_KURRENT":
|
||||
if not kraken_engine.is_available():
|
||||
raise HTTPException(
|
||||
@@ -119,6 +121,9 @@ async def run_ocr(request: OcrRequest):
|
||||
else:
|
||||
# TYPEWRITER, HANDWRITING_LATIN, UNKNOWN — all use Surya
|
||||
blocks = await asyncio.to_thread(surya_engine.extract_blocks, images, request.language)
|
||||
metrics.ocr_processing_seconds.labels(engine=engine_name).observe(
|
||||
time.monotonic() - extract_started
|
||||
)
|
||||
|
||||
metrics.ocr_jobs_total.labels(engine=engine_name, script_type=script_type).inc()
|
||||
|
||||
@@ -194,6 +199,7 @@ async def run_ocr_stream(request: OcrRequest):
|
||||
image = await asyncio.to_thread(preprocess_page, image)
|
||||
blocks = []
|
||||
sender_path = request.senderModelPath if use_kraken else None
|
||||
page_started = time.monotonic()
|
||||
for region in page_regions:
|
||||
text = await asyncio.to_thread(
|
||||
engine.extract_region_text, image,
|
||||
@@ -213,6 +219,9 @@ async def run_ocr_stream(request: OcrRequest):
|
||||
"annotationId": region.annotationId,
|
||||
})
|
||||
|
||||
metrics.ocr_processing_seconds.labels(engine=engine_name).observe(
|
||||
time.monotonic() - page_started
|
||||
)
|
||||
total_blocks += len(blocks)
|
||||
metrics.ocr_pages_total.labels(engine=engine_name).inc()
|
||||
yield json.dumps({
|
||||
@@ -258,9 +267,13 @@ async def run_ocr_stream(request: OcrRequest):
|
||||
yield json.dumps({"type": "preprocessing", "pageNumber": page_idx}) + "\n"
|
||||
image = await asyncio.to_thread(preprocess_page, image)
|
||||
sender_path = request.senderModelPath if use_kraken else None
|
||||
page_started = time.monotonic()
|
||||
blocks = await asyncio.to_thread(
|
||||
engine.extract_page_blocks, image, page_idx, request.language, sender_path
|
||||
)
|
||||
metrics.ocr_processing_seconds.labels(engine=engine_name).observe(
|
||||
time.monotonic() - page_started
|
||||
)
|
||||
|
||||
for block in blocks:
|
||||
words = block.get("words") or []
|
||||
|
||||
Reference in New Issue
Block a user