Skip to content

Commit

Permalink
Include support for config files and ini
Browse files Browse the repository at this point in the history
Handle multiprocessing logging
  • Loading branch information
dormant-user committed Aug 15, 2024
1 parent 30442a5 commit 2992cbc
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 38 deletions.
2 changes: 1 addition & 1 deletion nctl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import click

from nctl.main import tunnel # noqa: F401
from nctl.ngrok import tunnel # noqa: F401

version = "0.0.0-a"

Expand Down
14 changes: 8 additions & 6 deletions nctl/cloudfront.py → nctl/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
import yaml
from botocore.exceptions import ClientError

from nctl import models
from nctl.logger import LOGGER
from nctl import logger, models

LOGGER = logging.getLogger("nctl.cloudfront")


class CloudFront:
Expand All @@ -20,19 +21,20 @@ class CloudFront:
"""

def __init__(self, env_dump: dict):
def __init__(self, env_dump: dict, log_config: dict = None):
"""Initiates the boto3 client and re-configures the environment variables.
Args:
env_dump: JSON dump of environment variables' configuration.
"""
self.env = models.EnvConfig(**env_dump)
if self.env.debug:
LOGGER.setLevel(logging.DEBUG)
logger.configure_logging(
debug=self.env.debug, log_config=log_config, process="cloudfront"
)
session = boto3.Session(
aws_access_key_id=self.env.aws_access_key_id,
aws_secret_access_key=self.env.aws_secret_access_key,
region_name=self.env.aws_region_name,
region_name=self.env.aws_default_region,
profile_name=self.env.aws_profile_name,
)
self.client = session.client("cloudfront")
Expand Down
91 changes: 64 additions & 27 deletions nctl/logger.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import importlib
import json
import logging
from multiprocessing import current_process

pname = current_process().name
if pname == "MainProcess":
pname = "ngrok-cloudfront"
import yaml
from pydantic import BaseModel

LOGGER = logging.getLogger("nctl.tunnel")


class AddProcessName(logging.Filter):
Expand All @@ -27,27 +27,64 @@ def filter(self, record: logging.LogRecord) -> bool:
return True


def build_logger() -> logging.Logger:
"""Constructs a custom logger.
class LogConfig(BaseModel):
"""BaseModel object for log configurations.
>>> LogConfig
"""

debug: bool = False
process: str | None = None
log_config: dict | str | None = None

class Config:
"""Extra configuration for LogConfig object."""

extra = "ignore"


def configure_logging(**kwargs) -> None:
"""Configure logging based on the parameters.
Returns:
logging.Logger:
Returns a reference to the logger object.
Keyword Args:
debug: Boolean flag to enable/disable debug mode.
process: Name of the process to add a process name filter to default logging.
log_config: Custom logging configuration.
"""
# todo: add file logger functionality [OR]
# support logging.conf and logging.ini file support
importlib.reload(logging)
logger = logging.getLogger(__name__)
default_formatter = logging.Formatter(
datefmt="%b-%d-%Y %I:%M:%S %p",
fmt="%(asctime)s - %(levelname)s - [%(processName)s:%(module)s:%(lineno)d] - %(funcName)s - %(message)s",
)
handler = logging.StreamHandler()
handler.setFormatter(default_formatter)
logger.addHandler(handler)
logger.addFilter(filter=AddProcessName(process_name=pname))
logger.setLevel(logging.INFO)
return logger


LOGGER = build_logger()
config = LogConfig(**kwargs)
if not config.process:
config.process = "ngrok-cloudfront"
if config.log_config:
if isinstance(config.log_config, dict):
logging.config.dictConfig(config.log_config)
elif isinstance(config.log_config, str) and config.log_config.endswith(".json"):
with open(config.log_config) as file:
loaded_config = json.load(file)
logging.config.dictConfig(loaded_config)
elif isinstance(config.log_config, str) and config.log_config.endswith(
(".yaml", ".yml")
):
with open(config.log_config) as file:
loaded_config = yaml.safe_load(file)
logging.config.dictConfig(loaded_config)
else:
# See the note about fileConfig() here:
# https://docs.python.org/3/library/logging.config.html#configuration-file-format
logging.config.fileConfig(config.log_config, disable_existing_loggers=False)
else:
if config.debug:
log_level = logging.DEBUG
else:
log_level = logging.INFO
logging.getLogger(f"nctl.{config.process}").setLevel(log_level)
default_formatter = logging.Formatter(
datefmt="%b-%d-%Y %I:%M:%S %p",
fmt="%(asctime)s - %(levelname)s - [%(module)s:%(processName)s:%(lineno)d] - %(funcName)s - %(message)s",
)
handler = logging.StreamHandler()
handler.setFormatter(default_formatter)
logging.getLogger(f"nctl.{config.process}").addHandler(handler)
logging.getLogger(f"nctl.{config.process}").addFilter(
filter=AddProcessName(process_name=config.process)
)
1 change: 1 addition & 0 deletions nctl/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class EnvConfig(BaseSettings):
distribution_id: str | None = None
distribution_config: FilePath | None = None
debug: bool = False
log_config: dict | None = None

@classmethod
def from_env_file(cls, env_file: pathlib.Path) -> "EnvConfig":
Expand Down
11 changes: 8 additions & 3 deletions nctl/main.py → nctl/ngrok.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import logging
import multiprocessing
import os
import subprocess

from nctl import cloudfront, models, squire
from nctl.logger import LOGGER
from nctl import aws, logger, models, squire

LOGGER = logging.getLogger("nctl.tunnel")


# Have this as a dedicated function to avoid pickling error
Expand All @@ -14,7 +16,7 @@ def distribution_handler(public_url: str, env_dump: dict) -> None:
public_url: Public URL from ngrok, that has to be updated.
env_dump: env_dump: JSON dump of environment variables' configuration.
"""
cloud_front = cloudfront.CloudFront(env_dump)
cloud_front = aws.CloudFront(env_dump)
cloud_front.run(public_url)


Expand Down Expand Up @@ -63,6 +65,9 @@ def tunnel(**kwargs) -> None:
models.env = squire.env_loader(".env")
else:
models.env = models.EnvConfig(**kwargs)
logger.configure_logging(
debug=models.env.debug, log_config=models.env.log_config, process="tunnel"
)
squire.run_validations()

# https://ngrok.com/docs/agent/config/
Expand Down
4 changes: 3 additions & 1 deletion nctl/squire.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import json
import logging
import os
import pathlib
import shutil

import yaml

from nctl import models
from nctl.logger import LOGGER

LOGGER = logging.getLogger("nctl.tunnel")


def create_ngrok_config(token: str, filename: str) -> None:
Expand Down

0 comments on commit 2992cbc

Please sign in to comment.