Skip to content

Commit b491227

Browse files
author
Flamehaven CI
committed
Fix CI deps and format for 1.2.2
1 parent 7a743a3 commit b491227

File tree

10 files changed

+2013
-1991
lines changed

10 files changed

+2013
-1991
lines changed

flamehaven_filesearch/api.py

Lines changed: 1102 additions & 1101 deletions
Large diffs are not rendered by default.

flamehaven_filesearch/auth.py

Lines changed: 581 additions & 574 deletions
Large diffs are not rendered by default.

flamehaven_filesearch/encryption.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
try:
1313
from cryptography.fernet import Fernet, InvalidToken
14+
1415
_CRYPTO_AVAILABLE = True
1516
except ImportError: # pragma: no cover - fallback when cryptography missing
1617
_CRYPTO_AVAILABLE = False
@@ -27,7 +28,9 @@ def __init__(self, key: Optional[str] = None):
2728
if key and _CRYPTO_AVAILABLE:
2829
try:
2930
# Accept either raw Fernet key or 32-byte base64url
30-
self._fernet = Fernet(key.encode() if not key.startswith("gAAAA") else key)
31+
self._fernet = Fernet(
32+
key.encode() if not key.startswith("gAAAA") else key
33+
)
3134
self.enabled = True
3235
except Exception as exc: # pragma: no cover - defensive
3336
logger.warning("Invalid encryption key, disabling encryption: %s", exc)

flamehaven_filesearch/logging_config.py

Lines changed: 80 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,62 @@
44
Production-ready logging with JSON format for log aggregation systems.
55
"""
66

7-
import logging
8-
import sys
9-
10-
try:
11-
from pythonjsonlogger import jsonlogger
12-
_JSONLOGGER_AVAILABLE = True
13-
except ImportError: # pragma: no cover - fallback when dependency missing
14-
_JSONLOGGER_AVAILABLE = False
15-
jsonlogger = None
16-
17-
18-
if _JSONLOGGER_AVAILABLE:
19-
20-
class CustomJsonFormatter(jsonlogger.JsonFormatter):
21-
"""
22-
Custom JSON formatter with additional fields
23-
24-
Adds request_id, service_name, and environment to all log records.
25-
"""
26-
27-
def add_fields(self, log_record, record, message_dict):
28-
super(CustomJsonFormatter, self).add_fields(
29-
log_record, record, message_dict
30-
)
31-
32-
# Add service identification
33-
log_record["service"] = "flamehaven-filesearch"
34-
log_record["version"] = "1.2.2"
35-
36-
# Add request ID if available
37-
if hasattr(record, "request_id"):
38-
log_record["request_id"] = record.request_id
39-
40-
# Add environment (from env var or default to 'development')
41-
import os
42-
43-
log_record["environment"] = os.getenv("ENVIRONMENT", "development")
44-
45-
# Ensure timestamp is present
46-
if "timestamp" not in log_record:
47-
from datetime import datetime
48-
49-
log_record["timestamp"] = datetime.utcnow().isoformat() + "Z"
50-
51-
# Add level name
52-
log_record["level"] = record.levelname
53-
else:
54-
55-
class CustomJsonFormatter(logging.Formatter):
56-
"""Fallback plain formatter when python-json-logger is unavailable."""
57-
58-
def format(self, record):
59-
base = super().format(record)
60-
return base
7+
import logging
8+
import sys
9+
10+
try:
11+
from pythonjsonlogger import jsonlogger
12+
13+
_JSONLOGGER_AVAILABLE = True
14+
except ImportError: # pragma: no cover - fallback when dependency missing
15+
_JSONLOGGER_AVAILABLE = False
16+
jsonlogger = None
17+
18+
19+
if _JSONLOGGER_AVAILABLE:
20+
21+
class CustomJsonFormatter(jsonlogger.JsonFormatter):
22+
"""
23+
Custom JSON formatter with additional fields
24+
25+
Adds request_id, service_name, and environment to all log records.
26+
"""
27+
28+
def add_fields(self, log_record, record, message_dict):
29+
super(CustomJsonFormatter, self).add_fields(
30+
log_record, record, message_dict
31+
)
32+
33+
# Add service identification
34+
log_record["service"] = "flamehaven-filesearch"
35+
log_record["version"] = "1.2.2"
36+
37+
# Add request ID if available
38+
if hasattr(record, "request_id"):
39+
log_record["request_id"] = record.request_id
40+
41+
# Add environment (from env var or default to 'development')
42+
import os
43+
44+
log_record["environment"] = os.getenv("ENVIRONMENT", "development")
45+
46+
# Ensure timestamp is present
47+
if "timestamp" not in log_record:
48+
from datetime import datetime
49+
50+
log_record["timestamp"] = datetime.utcnow().isoformat() + "Z"
51+
52+
# Add level name
53+
log_record["level"] = record.levelname
54+
55+
else:
56+
57+
class CustomJsonFormatter(logging.Formatter):
58+
"""Fallback plain formatter when python-json-logger is unavailable."""
59+
60+
def format(self, record):
61+
base = super().format(record)
62+
return base
6163

6264

6365
def setup_json_logging(log_level=logging.INFO, **kwargs):
@@ -71,36 +73,36 @@ def setup_json_logging(log_level=logging.INFO, **kwargs):
7173
# Support logging.basicConfig-style signatures (level=...)
7274
effective_level = kwargs.get("level", log_level)
7375

74-
# Create JSON formatter (or fallback)
75-
if _JSONLOGGER_AVAILABLE:
76-
formatter = CustomJsonFormatter(
77-
"%(timestamp)s %(level)s %(name)s %(message)s %(request_id)s "
78-
"%(service)s %(version)s %(environment)s",
79-
rename_fields={
80-
"levelname": "level",
81-
"name": "logger",
82-
"asctime": "timestamp",
83-
},
84-
datefmt="%Y-%m-%dT%H:%M:%S",
85-
)
86-
else:
87-
formatter = logging.Formatter(
88-
"%(asctime)s %(levelname)s %(name)s %(message)s",
89-
datefmt="%Y-%m-%dT%H:%M:%S",
90-
)
76+
# Create JSON formatter (or fallback)
77+
if _JSONLOGGER_AVAILABLE:
78+
formatter = CustomJsonFormatter(
79+
"%(timestamp)s %(level)s %(name)s %(message)s %(request_id)s "
80+
"%(service)s %(version)s %(environment)s",
81+
rename_fields={
82+
"levelname": "level",
83+
"name": "logger",
84+
"asctime": "timestamp",
85+
},
86+
datefmt="%Y-%m-%dT%H:%M:%S",
87+
)
88+
else:
89+
formatter = logging.Formatter(
90+
"%(asctime)s %(levelname)s %(name)s %(message)s",
91+
datefmt="%Y-%m-%dT%H:%M:%S",
92+
)
9193

9294
# Configure root logger
9395
root_logger = logging.getLogger()
9496
root_logger.setLevel(effective_level)
9597

9698
# Remove existing handlers
97-
for handler in root_logger.handlers[:]:
98-
root_logger.removeHandler(handler)
99-
100-
# Add handler to stdout
101-
json_handler = logging.StreamHandler(sys.stdout)
102-
json_handler.setFormatter(formatter)
103-
root_logger.addHandler(json_handler)
99+
for handler in root_logger.handlers[:]:
100+
root_logger.removeHandler(handler)
101+
102+
# Add handler to stdout
103+
json_handler = logging.StreamHandler(sys.stdout)
104+
json_handler.setFormatter(formatter)
105+
root_logger.addHandler(json_handler)
104106

105107
# Set level for specific loggers
106108
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)

flamehaven_filesearch/metrics.py

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
registry = CollectorRegistry()
2727

2828
# Application info
29-
app_info = Info(
30-
"flamehaven_filesearch_app", "Application information", registry=registry
31-
)
32-
app_info.info(
33-
{"version": "1.2.2", "service": "flamehaven-filesearch", "framework": "fastapi"}
34-
)
29+
app_info = Info(
30+
"flamehaven_filesearch_app", "Application information", registry=registry
31+
)
32+
app_info.info(
33+
{"version": "1.2.2", "service": "flamehaven-filesearch", "framework": "fastapi"}
34+
)
3535

3636
# Request metrics
3737
http_requests_total = Counter(
@@ -164,11 +164,11 @@
164164
)
165165

166166

167-
_requests_ts = deque(maxlen=5000)
168-
_errors_ts = deque(maxlen=2000)
169-
170-
171-
class MetricsCollector:
167+
_requests_ts = deque(maxlen=5000)
168+
_errors_ts = deque(maxlen=2000)
169+
170+
171+
class MetricsCollector:
172172
"""
173173
Helper class for collecting and updating metrics
174174
"""
@@ -183,27 +183,27 @@ def _sum_metric(name: str) -> float:
183183
total += float(sample.value)
184184
return total
185185

186-
@staticmethod
187-
def summary() -> dict:
188-
"""Lightweight summary for /metrics JSON endpoint."""
189-
now = time.time()
190-
req_60 = len([t for t in _requests_ts if now - t <= 60])
191-
req_300 = len([t for t in _requests_ts if now - t <= 300])
192-
err_60 = len([t for t in _errors_ts if now - t <= 60])
193-
err_300 = len([t for t in _errors_ts if now - t <= 300])
194-
return {
195-
"requests_total": MetricsCollector._sum_metric("http_requests_total"),
196-
"errors_total": MetricsCollector._sum_metric("errors_total"),
197-
"rate_limit_exceeded": MetricsCollector._sum_metric(
198-
"rate_limit_exceeded_total"
199-
),
200-
"cache_hits_total": MetricsCollector._sum_metric("cache_hits_total"),
201-
"cache_misses_total": MetricsCollector._sum_metric("cache_misses_total"),
202-
"requests_last_60s": req_60,
203-
"requests_last_300s": req_300,
204-
"errors_last_60s": err_60,
205-
"errors_last_300s": err_300,
206-
}
186+
@staticmethod
187+
def summary() -> dict:
188+
"""Lightweight summary for /metrics JSON endpoint."""
189+
now = time.time()
190+
req_60 = len([t for t in _requests_ts if now - t <= 60])
191+
req_300 = len([t for t in _requests_ts if now - t <= 300])
192+
err_60 = len([t for t in _errors_ts if now - t <= 60])
193+
err_300 = len([t for t in _errors_ts if now - t <= 300])
194+
return {
195+
"requests_total": MetricsCollector._sum_metric("http_requests_total"),
196+
"errors_total": MetricsCollector._sum_metric("errors_total"),
197+
"rate_limit_exceeded": MetricsCollector._sum_metric(
198+
"rate_limit_exceeded_total"
199+
),
200+
"cache_hits_total": MetricsCollector._sum_metric("cache_hits_total"),
201+
"cache_misses_total": MetricsCollector._sum_metric("cache_misses_total"),
202+
"requests_last_60s": req_60,
203+
"requests_last_300s": req_300,
204+
"errors_last_60s": err_60,
205+
"errors_last_300s": err_300,
206+
}
207207

208208
@staticmethod
209209
def record_request(method: str, endpoint: str, status: int, duration: float):
@@ -227,7 +227,6 @@ def record_request(method: str, endpoint: str, status: int, duration: float):
227227
while _requests_ts and now - _requests_ts[0] > 300:
228228
_requests_ts.popleft()
229229

230-
231230
@staticmethod
232231
def record_file_upload(store: str, size_bytes: int, duration: float, success: bool):
233232
"""
@@ -295,7 +294,6 @@ def record_error(error_type: str, endpoint: str):
295294
while _errors_ts and now - _errors_ts[0] > 300:
296295
_errors_ts.popleft()
297296

298-
299297
@staticmethod
300298
def update_system_metrics():
301299
"""

0 commit comments

Comments
 (0)