Spaces:
Running
Running
Commit
Β·
6c983cf
1
Parent(s):
7fb47c4
Add logging functionality to app.py and blob_utils.py for improved traceability and debugging
Browse files- app.py +13 -1
- blob_utils.py +15 -11
- logging_config.py +84 -0
app.py
CHANGED
@@ -19,10 +19,14 @@ from utils import (
|
|
19 |
)
|
20 |
from flagging import HuggingFaceDatasetSaver
|
21 |
from blob_utils import decode_blob_data, is_blob_data
|
|
|
22 |
|
23 |
import install_private_repos # noqa: F401
|
24 |
from seavision import load_model
|
25 |
|
|
|
|
|
|
|
26 |
|
27 |
TITLE = """
|
28 |
<h1> π SEA.AI's Vision Demo β¨ </h1>
|
@@ -48,6 +52,8 @@ h1 {
|
|
48 |
}
|
49 |
"""
|
50 |
|
|
|
|
|
51 |
model = load_model("experimental/ahoy6-MIX-1280-b1.onnx")
|
52 |
model.det_conf_thresh = 0.1
|
53 |
model.hor_conf_thresh = 0.1
|
@@ -56,18 +62,24 @@ model.hor_conf_thresh = 0.1
|
|
56 |
# @spaces.GPU
|
57 |
def inference(image):
|
58 |
"""Run inference on image and return annotated image."""
|
|
|
59 |
results = model(image)
|
|
|
60 |
return results.draw(image)
|
61 |
|
62 |
|
63 |
def flag_img_input(
|
64 |
image: gr.Image, flag_option: str = "misdetection", username: str = "anonymous"
|
65 |
):
|
66 |
-
"""Wrapper for flagging"""
|
|
|
|
|
67 |
# Decode blob data if necessary
|
68 |
if is_blob_data(image):
|
69 |
image = decode_blob_data(image)
|
|
|
70 |
hf_writer.flag([image], flag_option=flag_option, username=username)
|
|
|
71 |
|
72 |
|
73 |
# Flagging
|
|
|
19 |
)
|
20 |
from flagging import HuggingFaceDatasetSaver
|
21 |
from blob_utils import decode_blob_data, is_blob_data
|
22 |
+
from logging_config import get_logger
|
23 |
|
24 |
import install_private_repos # noqa: F401
|
25 |
from seavision import load_model
|
26 |
|
27 |
+
# Get loggers
|
28 |
+
logger = get_logger()
|
29 |
+
|
30 |
|
31 |
TITLE = """
|
32 |
<h1> π SEA.AI's Vision Demo β¨ </h1>
|
|
|
52 |
}
|
53 |
"""
|
54 |
|
55 |
+
# Load model
|
56 |
+
logger.info("Loading detection model...")
|
57 |
model = load_model("experimental/ahoy6-MIX-1280-b1.onnx")
|
58 |
model.det_conf_thresh = 0.1
|
59 |
model.hor_conf_thresh = 0.1
|
|
|
62 |
# @spaces.GPU
|
63 |
def inference(image):
|
64 |
"""Run inference on image and return annotated image."""
|
65 |
+
logger.debug("Running inference on image")
|
66 |
results = model(image)
|
67 |
+
logger.debug("Inference completed")
|
68 |
return results.draw(image)
|
69 |
|
70 |
|
71 |
def flag_img_input(
|
72 |
image: gr.Image, flag_option: str = "misdetection", username: str = "anonymous"
|
73 |
):
|
74 |
+
"""Wrapper for flagging"""
|
75 |
+
logger.info("Flagging image - option: %s, user: %s", flag_option, username)
|
76 |
+
|
77 |
# Decode blob data if necessary
|
78 |
if is_blob_data(image):
|
79 |
image = decode_blob_data(image)
|
80 |
+
|
81 |
hf_writer.flag([image], flag_option=flag_option, username=username)
|
82 |
+
logger.info("Image flagged successfully")
|
83 |
|
84 |
|
85 |
# Flagging
|
blob_utils.py
CHANGED
@@ -6,6 +6,10 @@ Handles conversion of blob data to proper image file formats.
|
|
6 |
import hashlib
|
7 |
import os
|
8 |
from typing import Dict, Any
|
|
|
|
|
|
|
|
|
9 |
|
10 |
|
11 |
class BlobConverter:
|
@@ -86,35 +90,35 @@ class BlobConverter:
|
|
86 |
if not cls.is_blob_data(image_data):
|
87 |
return image_data
|
88 |
|
89 |
-
|
90 |
|
91 |
blob_path = image_data["path"]
|
92 |
-
|
93 |
|
94 |
# Read blob content
|
95 |
with open(blob_path, "rb") as f:
|
96 |
content = f.read()
|
97 |
|
98 |
file_size = len(content)
|
99 |
-
|
100 |
|
101 |
# Detect format
|
102 |
extension, mime_type = cls.detect_format(content)
|
103 |
-
|
104 |
|
105 |
# Generate filename and path
|
106 |
filename = cls.generate_filename(content, extension)
|
107 |
temp_dir = os.path.dirname(blob_path)
|
108 |
new_path = os.path.join(temp_dir, filename)
|
109 |
|
110 |
-
|
111 |
-
|
112 |
|
113 |
# Write converted file
|
114 |
with open(new_path, "wb") as f:
|
115 |
f.write(content)
|
116 |
|
117 |
-
|
118 |
|
119 |
# Return updated image data
|
120 |
converted_data = {
|
@@ -127,7 +131,7 @@ class BlobConverter:
|
|
127 |
"meta": image_data.get("meta", {}),
|
128 |
}
|
129 |
|
130 |
-
|
131 |
return converted_data
|
132 |
|
133 |
|
@@ -141,14 +145,14 @@ def decode_blob_data(image_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
141 |
Returns:
|
142 |
Converted image data or original data if not a blob
|
143 |
"""
|
144 |
-
|
145 |
|
146 |
result = BlobConverter.convert_blob(image_data)
|
147 |
|
148 |
if result is image_data:
|
149 |
-
|
150 |
else:
|
151 |
-
|
152 |
|
153 |
return result
|
154 |
|
|
|
6 |
import hashlib
|
7 |
import os
|
8 |
from typing import Dict, Any
|
9 |
+
from logging_config import get_logger
|
10 |
+
|
11 |
+
# Module logger
|
12 |
+
logger = get_logger("blob_utils")
|
13 |
|
14 |
|
15 |
class BlobConverter:
|
|
|
90 |
if not cls.is_blob_data(image_data):
|
91 |
return image_data
|
92 |
|
93 |
+
logger.info("Converting blob data: %s", image_data)
|
94 |
|
95 |
blob_path = image_data["path"]
|
96 |
+
logger.debug("Blob path: %s", blob_path)
|
97 |
|
98 |
# Read blob content
|
99 |
with open(blob_path, "rb") as f:
|
100 |
content = f.read()
|
101 |
|
102 |
file_size = len(content)
|
103 |
+
logger.debug("File size: %d bytes", file_size)
|
104 |
|
105 |
# Detect format
|
106 |
extension, mime_type = cls.detect_format(content)
|
107 |
+
logger.debug("Detected format: %s, MIME type: %s", extension, mime_type)
|
108 |
|
109 |
# Generate filename and path
|
110 |
filename = cls.generate_filename(content, extension)
|
111 |
temp_dir = os.path.dirname(blob_path)
|
112 |
new_path = os.path.join(temp_dir, filename)
|
113 |
|
114 |
+
logger.debug("Generated filename: %s", filename)
|
115 |
+
logger.debug("New path: %s", new_path)
|
116 |
|
117 |
# Write converted file
|
118 |
with open(new_path, "wb") as f:
|
119 |
f.write(content)
|
120 |
|
121 |
+
logger.info("Successfully converted blob to: %s", new_path)
|
122 |
|
123 |
# Return updated image data
|
124 |
converted_data = {
|
|
|
131 |
"meta": image_data.get("meta", {}),
|
132 |
}
|
133 |
|
134 |
+
logger.debug("Converted data: %s", converted_data)
|
135 |
return converted_data
|
136 |
|
137 |
|
|
|
145 |
Returns:
|
146 |
Converted image data or original data if not a blob
|
147 |
"""
|
148 |
+
logger.debug("Processing image data: %s", image_data)
|
149 |
|
150 |
result = BlobConverter.convert_blob(image_data)
|
151 |
|
152 |
if result is image_data:
|
153 |
+
logger.debug("Not a blob, skipping conversion")
|
154 |
else:
|
155 |
+
logger.info("Blob conversion completed")
|
156 |
|
157 |
return result
|
158 |
|
logging_config.py
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Logging configuration for the detection demo application.
|
3 |
+
Provides centralized logging setup with proper formatting and levels.
|
4 |
+
"""
|
5 |
+
|
6 |
+
import logging
|
7 |
+
import sys
|
8 |
+
from pathlib import Path
|
9 |
+
|
10 |
+
|
11 |
+
class LoggerManager:
|
12 |
+
"""Singleton logger manager for the application."""
|
13 |
+
|
14 |
+
_instance = None
|
15 |
+
_initialized = False
|
16 |
+
|
17 |
+
def __new__(cls):
|
18 |
+
if cls._instance is None:
|
19 |
+
cls._instance = super().__new__(cls)
|
20 |
+
return cls._instance
|
21 |
+
|
22 |
+
def __init__(self):
|
23 |
+
if not self._initialized:
|
24 |
+
self._setup_default_logging()
|
25 |
+
self._initialized = True
|
26 |
+
|
27 |
+
def _setup_default_logging(self):
|
28 |
+
"""Setup default logging configuration."""
|
29 |
+
# Create main logger
|
30 |
+
self.logger = logging.getLogger("detection-demo")
|
31 |
+
self.logger.setLevel(logging.INFO)
|
32 |
+
|
33 |
+
# Prevent duplicate handlers
|
34 |
+
if self.logger.handlers:
|
35 |
+
return
|
36 |
+
|
37 |
+
# Console handler
|
38 |
+
console_handler = logging.StreamHandler(sys.stdout)
|
39 |
+
console_handler.setLevel(logging.INFO)
|
40 |
+
console_formatter = logging.Formatter(
|
41 |
+
fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
42 |
+
datefmt="%H:%M:%S",
|
43 |
+
)
|
44 |
+
console_handler.setFormatter(console_formatter)
|
45 |
+
self.logger.addHandler(console_handler)
|
46 |
+
|
47 |
+
# File handler (logs/app.log)
|
48 |
+
log_file = Path("logs/app.log")
|
49 |
+
log_file.parent.mkdir(parents=True, exist_ok=True)
|
50 |
+
file_handler = logging.FileHandler(log_file)
|
51 |
+
file_handler.setLevel(logging.DEBUG)
|
52 |
+
file_formatter = logging.Formatter(
|
53 |
+
fmt="%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s",
|
54 |
+
datefmt="%Y-%m-%d %H:%M:%S",
|
55 |
+
)
|
56 |
+
file_handler.setFormatter(file_formatter)
|
57 |
+
self.logger.addHandler(file_handler)
|
58 |
+
|
59 |
+
def get_logger(self, name: str = None) -> logging.Logger:
|
60 |
+
"""Get a logger instance."""
|
61 |
+
if name:
|
62 |
+
return logging.getLogger(f"detection-demo.{name}")
|
63 |
+
return self.logger
|
64 |
+
|
65 |
+
|
66 |
+
# Global logger manager instance
|
67 |
+
_logger_manager = LoggerManager()
|
68 |
+
|
69 |
+
|
70 |
+
def get_logger(name: str = None) -> logging.Logger:
|
71 |
+
"""
|
72 |
+
Get a logger instance for the application.
|
73 |
+
|
74 |
+
Args:
|
75 |
+
name: Optional module name (will be prefixed with app name)
|
76 |
+
|
77 |
+
Returns:
|
78 |
+
Logger instance
|
79 |
+
"""
|
80 |
+
return _logger_manager.get_logger(name)
|
81 |
+
|
82 |
+
|
83 |
+
# Module-level logger
|
84 |
+
logger = get_logger(__name__)
|