Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logging configuration for Gunicorn and Uvicorn #3

Merged
merged 27 commits into from
Aug 20, 2020
Merged
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
37466c7
Add logging configuration modules
br3ndonland Aug 16, 2020
524adbe
Create README section for logging configuration
br3ndonland Aug 16, 2020
1da6c66
Add new logging configuration options to README
br3ndonland Aug 17, 2020
40f8a2b
Add logging info to README description section
br3ndonland Aug 17, 2020
cd3fe7b
Improve logging config file format info in README
br3ndonland Aug 17, 2020
0e9a766
Add command for building Docker images to README
br3ndonland Aug 17, 2020
1b2cc1c
Add separate COPY command for application files
br3ndonland Aug 17, 2020
cd8de6b
Install PyYAML to parse YAML configuration files
br3ndonland Aug 17, 2020
cf8f71c
Set path to logging configuration module
br3ndonland Aug 16, 2020
e2fa04a
Add docstrings to functions in start.py
br3ndonland Aug 17, 2020
b05a498
Add logging configuration function to start.py
br3ndonland Aug 17, 2020
e9b27ce
Add logging to start.py
br3ndonland Aug 17, 2020
a294862
Return logging dictionary config after loading
br3ndonland Aug 18, 2020
bf62cc8
Remove PROPAGATE_ACCESS_LOGS environment variable
br3ndonland Aug 18, 2020
8c81eba
Specify logging handlers for gunicorn.access
br3ndonland Aug 18, 2020
271a7b0
Add module name to log message formatter
br3ndonland Aug 18, 2020
1a9a826
Drop support for YAML and INI logging config files
br3ndonland Aug 18, 2020
591458f
Improve logging and return types in start.py
br3ndonland Aug 19, 2020
6e66d98
Configure Gunicorn logging programmatically
br3ndonland Aug 19, 2020
f6ca7da
Configure Uvicorn logging programmatically
br3ndonland Aug 20, 2020
27896dd
Add support for multiple log message formatters
br3ndonland Aug 20, 2020
197feda
Add Uvicorn VSCode debugger config
br3ndonland Aug 19, 2020
60aa2ca
Proofread README
br3ndonland Aug 20, 2020
57f777b
Improve selectivity of Docker COPY command
br3ndonland Aug 20, 2020
00a3319
Restrict Gunicorn configuration output to debug
br3ndonland Aug 20, 2020
83770ee
Remove redundant Dockerfile environment variable
br3ndonland Aug 20, 2020
46e9407
:ship: Add emoji to README title :whale:
br3ndonland Aug 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improve logging and return types in start.py
start.py configure_logging

- Simplify return statement: just return a dict

start.py run_pre_start_script

- If pre-start script is not found, log a message instead of raising an
  exception (pre-start script is optional)
- Use `finally` to wrap return statement
  • Loading branch information
br3ndonland committed Aug 20, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 591458fe191ee688f4654f5052428ecb265f1a2e
50 changes: 26 additions & 24 deletions inboard/start.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
import subprocess
from logging import Logger
from pathlib import Path
from typing import Any, Dict, Union
from typing import Any, Dict

import uvicorn # type: ignore

@@ -28,29 +28,30 @@ def set_conf_path(module: str) -> Path:

def configure_logging(
logger: Logger = logging.getLogger(), logging_conf: Path = Path("/logging_conf.py")
) -> Union[Dict[str, Any], str]:
) -> Dict[str, Any]:
"""Configure Python logging based on a path to a logging configuration file."""
try:
if logging_conf.suffix != ".py":
raise ImportError(f"{logging_conf.name} must have a .py extension.")
spec = importlib.util.spec_from_file_location("confspec", logging_conf)
logging_conf_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(logging_conf_module) # type: ignore
if getattr(logging_conf_module, "LOGGING_CONFIG"):
logging_conf_dict = getattr(logging_conf_module, "LOGGING_CONFIG")
if isinstance(logging_conf, Path) and logging_conf.suffix == ".py":
spec = importlib.util.spec_from_file_location("confspec", logging_conf)
logging_conf_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(logging_conf_module) # type: ignore
if getattr(logging_conf_module, "LOGGING_CONFIG"):
logging_conf_dict = getattr(logging_conf_module, "LOGGING_CONFIG")
else:
raise AttributeError(f"No LOGGING_CONFIG in {logging_conf_module}.")
if isinstance(logging_conf_dict, dict):
logging.config.dictConfig(logging_conf_dict)
message = f"Logging dict config loaded from {logging_conf}."
logger.debug(message)
return logging_conf_dict
else:
raise TypeError("LOGGING_CONFIG is not a dictionary instance.")
else:
raise AttributeError(f"No LOGGING_CONFIG in {logging_conf_module}.")
if isinstance(logging_conf_dict, dict):
logging.config.dictConfig(logging_conf_dict)
message = f"Logging dict config loaded from {logging_conf}."
logger.debug(message)
return logging_conf_dict
else:
raise TypeError("LOGGING_CONFIG is not a dictionary instance.")
raise ImportError("Valid path to .py logging config file required.")
except Exception as e:
message = f"Error when configuring logging: {e}"
logger.debug(message)
return message
raise


def set_app_module(logger: Logger = logging.getLogger()) -> str:
@@ -73,24 +74,25 @@ def run_pre_start_script(logger: Logger = logging.getLogger()) -> str:
"""Run a pre-start script at the provided path."""
try:
logger.debug("Checking for pre-start script.")
pre_start_path_var = str(os.getenv("PRE_START_PATH", "/app/prestart.py"))
pre_start_path = None
pre_start_path_var = os.getenv("PRE_START_PATH", "/app/prestart.py")
if Path(pre_start_path_var).is_file():
pre_start_path = pre_start_path_var
elif Path("/app/app/prestart.py").is_file():
pre_start_path = "/app/app/prestart.py"
else:
message = "No pre-start script found."
if pre_start_path:
process = "python" if Path(pre_start_path).suffix == ".py" else "sh"
run_message = f"Running pre-start script with {process} {pre_start_path}."
logger.debug(run_message)
subprocess.run([process, pre_start_path])
message = f"Ran pre-start script with {process} {pre_start_path}."
else:
message = "No pre-start script found."
raise FileNotFoundError(message)
except Exception as e:
message = f"Error from pre-start script: {e}"
logger.debug(message)
return message
finally:
logger.debug(message)
return message


def start_server(