Skip to content

Commit 6f35bda

Browse files
author
Veinar
committed
Added basic logging logic
1 parent 4ec3f4c commit 6f35bda

File tree

5 files changed

+82
-37
lines changed

5 files changed

+82
-37
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
[V|venv]
12
[I|i]nclude
23
[L|l]ib
34
[S|s]cripts

dracan/core/app_factory.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ def create_app():
1111
"""
1212
app = Flask(__name__)
1313

14+
# Set up logging
15+
setup_logging(app)
16+
1417
# Load configurations
1518
proxy_config = load_proxy_config()
1619
rules_config = load_rules_config()
@@ -20,9 +23,9 @@ def create_app():
2023
json_validation_enabled = os.getenv("JSON_VALIDATION_ENABLED", "true").lower() == "true"
2124
rate_limiting_enabled = os.getenv("RATE_LIMITING_ENABLED", "true").lower() == "true"
2225

23-
# Create validators if flags are set
24-
validate_method = create_method_validator(rules_config) if method_validation_enabled else lambda: (True, None)
25-
validate_json = create_json_validator(rules_config) if json_validation_enabled else lambda: (True, None)
26+
# Create validators and pass the app logger
27+
validate_method = create_method_validator(rules_config, app.logger) if method_validation_enabled else lambda: (True, None)
28+
validate_json = create_json_validator(rules_config, app.logger) if json_validation_enabled else lambda: (True, None)
2629

2730
# Apply rate limiter if enabled
2831
if rate_limiting_enabled:
@@ -31,10 +34,34 @@ def create_app():
3134
# Route handling
3235
@app.route('/', methods=['GET', 'POST', 'PUT', 'DELETE'])
3336
def proxy_route_without_sub():
37+
app.logger.info(f"Proxying request without sub-path")
3438
return handle_proxy(proxy_config, rules_config, validate_method, validate_json)
3539

3640
@app.route('/<path:sub>', methods=['GET', 'POST', 'PUT', 'DELETE'])
3741
def proxy_route(sub):
42+
app.logger.info(f"Proxying request to sub-path: {sub}")
3843
return handle_proxy(proxy_config, rules_config, validate_method, validate_json, sub=sub)
3944

4045
return app
46+
47+
def setup_logging(app):
48+
"""
49+
Set up logging for the Flask app.
50+
"""
51+
# Set the log level (can be adjusted as needed)
52+
log_level = os.getenv("LOG_LEVEL", "INFO").upper()
53+
54+
# Configure logging for the application
55+
import logging
56+
logging.basicConfig(
57+
level=log_level, # Set the logging level
58+
format="%(asctime)s [%(levelname)s] %(message)s", # Log format
59+
handlers=[
60+
logging.StreamHandler(), # Log to console
61+
#logging.FileHandler("app.log", mode='a') # Optionally log to a file
62+
]
63+
)
64+
65+
# Override Flask's default logger with the configured one
66+
app.logger.setLevel(log_level)
67+
app.logger.info("Logger setup complete.")

dracan/core/proxy.py

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from flask import request, jsonify
1+
from flask import request, jsonify, current_app as app
22
import requests
33
import json
44

@@ -26,21 +26,32 @@ def forward_request(request, sub, config):
2626
:param sub: The additional path after the base URL.
2727
:return: Response from the destination service.
2828
"""
29+
# Build the destination URL based on the proxy configuration and subpath
2930
if sub is None:
3031
destination_url = f"http://{config['destination']['host']}:{config['destination']['port']}{config['destination']['path']}"
3132
else:
32-
destination_url = f"http://{config['destination']['host']}:{config['destination']['port']}{config['destination']['path']}/{sub}"
33-
34-
if request.method == 'GET':
35-
response = requests.get(destination_url, headers=request.headers, params=request.args)
36-
elif request.method == 'POST':
37-
response = requests.post(destination_url, headers=request.headers, json=request.get_json())
38-
elif request.method == 'PUT':
39-
response = requests.put(destination_url, headers=request.headers, json=request.get_json())
40-
elif request.method == 'DELETE':
41-
response = requests.delete(destination_url, headers=request.headers)
42-
43-
return response
33+
destination_url = f"http://{config['destination']['host']}:{config['destination']['port']}{config['destination']['path']}{sub}"
34+
35+
app.logger.info(f"Forwarding {request.method} request to {destination_url}") # Log request forwarding
36+
37+
# Forward the request based on its method
38+
try:
39+
if request.method == 'GET':
40+
response = requests.get(destination_url, headers=request.headers, params=request.args)
41+
elif request.method == 'POST':
42+
response = requests.post(destination_url, headers=request.headers, json=request.get_json())
43+
elif request.method == 'PUT':
44+
response = requests.put(destination_url, headers=request.headers, json=request.get_json())
45+
elif request.method == 'DELETE':
46+
response = requests.delete(destination_url, headers=request.headers)
47+
48+
app.logger.info(f"Received {response.status_code} from {destination_url}") # Log response status
49+
return response
50+
51+
except requests.exceptions.RequestException as e:
52+
# Log any exception that occurs during forwarding
53+
app.logger.error(f"Error forwarding request to {destination_url}: {str(e)}")
54+
raise
4455

4556
def handle_proxy(config, rules_config, validate_method, validate_json, sub=None):
4657
"""
@@ -56,18 +67,21 @@ def handle_proxy(config, rules_config, validate_method, validate_json, sub=None)
5667
# First, validate the method
5768
is_valid, validation_response = validate_method()
5869
if not is_valid:
59-
return validation_response # Return the error response if the method is not allowed
70+
app.logger.warning("Method validation failed") # Log method validation failure
71+
return validation_response
6072

6173
# Then, validate the request's JSON (if applicable)
6274
is_valid, validation_response = validate_json()
6375
if not is_valid:
64-
return validation_response # Return the error response if the JSON is invalid
76+
app.logger.warning("JSON validation failed") # Log JSON validation failure
77+
return validation_response
6578

6679
# If both validations pass, forward the request
6780
try:
6881
response = forward_request(request, sub, config)
6982
return (response.content, response.status_code, response.headers.items())
7083

7184
except Exception as e:
72-
# Handle any exception during the forwarding process
73-
return jsonify({'error': str(e)}), 500
85+
# Handle any exception during the forwarding process and log it
86+
app.logger.error(f"Error during request forwarding: {str(e)}")
87+
return jsonify({'error': str(e)}), 500

dracan/validators/json_validator.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,34 @@
11
from flask import request, jsonify
22
from jsonschema import validate, ValidationError
33

4-
def validate_json(data, schema):
4+
def validate_json(data, schema, logger):
55
"""
66
Validate the given JSON data against the provided schema, including required fields.
77
88
:param data: The JSON data to validate.
9-
:param schema: The schema to validate against, which includes 'required' fields.
9+
:param schema: The schema to validate against, which includes required fields.
10+
:param logger: The logger to use for logging.
1011
:return: Tuple (is_valid, error_message).
1112
"""
1213
try:
1314
# Validate the data against the schema, which includes required fields
1415
validate(instance=data, schema=schema)
16+
logger.info("JSON validation passed.") # Log successful validation
1517
return True, None
1618
except ValidationError as e:
1719
# Return False and a clear error message if validation fails
20+
logger.error(f"JSON validation failed: {str(e)}") # Log validation error
1821
return False, str(e)
1922

20-
def create_json_validator(rules_config):
23+
def create_json_validator(rules_config, logger):
2124
"""
2225
Creates a function that validates the request JSON based on the provided rules_config.
2326
2427
:param rules_config: The configuration that contains JSON validation rules, including the JSON schema.
28+
:param logger: The logger to use for logging.
2529
:return: A validation function or None if JSON validation is disabled.
2630
"""
27-
json_validation_enabled = rules_config.get("json_validation_enabled", False)
31+
json_validation_enabled = rules_config.get("json_validation_enabled", False)
2832
json_schema = rules_config.get("json_schema", {})
2933
detailed_errors_enabled = rules_config.get("detailed_errors_enabled", False) # Default to False
3034

@@ -35,17 +39,16 @@ def validate_json_request():
3539
"""
3640
if json_validation_enabled and request.method in ['POST', 'PUT']:
3741
data = request.get_json()
38-
is_valid, error_message = validate_json(data, json_schema)
42+
is_valid, error_message = validate_json(data, json_schema, logger)
3943
if not is_valid:
40-
# Determine whether to include detailed error information
4144
error_message_to_display = error_message if detailed_errors_enabled else "Invalid JSON format"
42-
# Return False and a 400 Bad Request response with only two values
45+
logger.warning(f"Invalid JSON: {error_message_to_display}") # Log failed request
4346
return False, (jsonify({'error': f"{error_message_to_display}"}), 400)
4447
return True, None
4548

4649
if json_validation_enabled:
47-
print("JSON validation is enabled")
50+
logger.info("JSON validation is enabled.")
4851
else:
49-
print("JSON validation is disabled")
52+
logger.info("JSON validation is disabled.")
5053

5154
return validate_json_request

dracan/validators/method_validator.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from flask import request, jsonify
22

3-
def create_method_validator(rules_config):
3+
def create_method_validator(rules_config, logger):
44
"""
55
Creates a function that validates if the request method is allowed based on the provided rules_config.
66
77
:param rules_config: The configuration that contains allowed methods and whether method validation is enabled.
8+
:param logger: The logger from the Flask app to use for logging.
89
:return: A validation function for HTTP methods.
910
"""
1011
allowed_methods = rules_config.get("allowed_methods", ["GET", "PUT", "POST", "DELETE"])
@@ -16,20 +17,19 @@ def validate_http_method():
1617
:return: Tuple (is_valid, response) - is_valid is True if valid, False otherwise.
1718
"""
1819
if not method_validation_enabled:
19-
# If method validation is disabled, always return True
20+
logger.info("Method validation is disabled.")
2021
return True, None
2122

2223
if request.method not in allowed_methods:
23-
# Return False and a validation response with a 405 status code if method is not allowed
24+
logger.warning(f"Method {request.method} not allowed.") # Log disallowed method
2425
return False, (jsonify({'error': f"Method {request.method} not allowed"}), 405)
25-
26-
# Return True and None if the method is allowed
26+
27+
logger.info(f"Method {request.method} is allowed.") # Log allowed method
2728
return True, None
2829

2930
if method_validation_enabled:
30-
print("HTTP Method validation is enabled, allowed methods: " + " | ".join(allowed_methods))
31+
logger.info("HTTP Method validation is enabled. Allowed methods: " + " | ".join(allowed_methods))
3132
else:
32-
print("HTTP Method validation is disabled")
33-
33+
logger.info("HTTP Method validation is disabled.")
3434

3535
return validate_http_method

0 commit comments

Comments
 (0)