Browse Source

Work on logging on backend.

pull/109/head
Per-Arne Andersen 4 years ago
parent
commit
4669d0956b
  1. 3
      wg-manager-backend/database/util.py
  2. 86
      wg-manager-backend/db/wireguard.py
  3. 21
      wg-manager-backend/logger.py
  4. 11
      wg-manager-backend/logging.json
  5. 18
      wg-manager-backend/main.py
  6. 7
      wg-manager-backend/middleware.py
  7. 3
      wg-manager-backend/migrations/env.py
  8. 1
      wg-manager-backend/requirements.txt
  9. 9
      wg-manager-backend/util.py

3
wg-manager-backend/database/util.py

@ -1,3 +1,4 @@
import contextlib
import os
import alembic.command
@ -14,9 +15,11 @@ from loguru import logger
def perform_migrations():
logger.info("Performing migrations...")
alembic_cfg = Config("alembic.ini")
alembic_cfg.attributes['configure_logger'] = False
alembic_cfg.set_main_option('script_location', "migrations")
alembic_cfg.set_main_option('sqlalchemy.url', str(engine.url))
alembic.command.upgrade(alembic_cfg, 'head')
logger.info("Migrations done!")

86
wg-manager-backend/db/wireguard.py

@ -11,10 +11,9 @@ import script.wireguard
from sqlalchemy.orm import Session
from database import models
import schemas
import logging
from loguru import logger
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.DEBUG)
from util import WGMHTTPException
def start_client(sess: Session, peer: schemas.WGPeer):
@ -161,8 +160,8 @@ def server_add_on_init(sess: Session):
# Only add if it does not already exists.
server_add(schemas.WGServerAdd(**init_data), sess, start=const.SERVER_INIT_INTERFACE_START)
except Exception as e:
_LOGGER.warning("Failed to setup initial server interface with exception:")
_LOGGER.exception(e)
logger.warning("Failed to setup initial server interface with exception:")
logger.exception(e)
def server_add(server: schemas.WGServerAdd, sess: Session, start=False):
@ -180,43 +179,54 @@ def server_add(server: schemas.WGServerAdd, sess: Session, start=False):
peers = server.peers if server.peers else []
# Public/Private key
try:
all_interfaces = sess.query(models.WGServer).all()
check_interface_exists = any(map(lambda el: el.interface == server.interface, all_interfaces))
check_v4_address_exists = any(map(lambda el: el.address == server.address, all_interfaces))
check_v6_address_exists = any(map(lambda el: el.v6_address == server.v6_address, all_interfaces))
check_listen_port_exists = any(map(lambda el: el.listen_port == server.listen_port, all_interfaces))
if check_interface_exists:
raise WGMHTTPException(
status_code=400,
detail=f"There is already a interface with the name: {server.interface}")
if check_v4_address_exists:
raise WGMHTTPException(
status_code=400,
detail=f"There is already a interface with the IPv4 address: {server.address}")
if check_v6_address_exists:
raise WGMHTTPException(
status_code=400,
detail=f"There is already a interface with the IPv6 address: {server.v6_address}")
if check_listen_port_exists:
raise WGMHTTPException(
status_code=400,
detail=f"There is already a interface listening on port: {server.listen_port}")
if not server.private_key:
keys = script.wireguard.generate_keys()
server.private_key = keys["private_key"]
server.public_key = keys["public_key"]
if sess.query(models.WGServer) \
.filter(
(models.WGServer.interface == server.interface) |
(models.WGServer.address == server.address) |
(models.WGServer.v6_address == server.v6_address)).count() != 0:
raise HTTPException(status_code=400,
detail="The server interface or ip %s already exists in the database" % server.interface)
if not server.private_key:
keys = script.wireguard.generate_keys()
server.private_key = keys["private_key"]
server.public_key = keys["public_key"]
server.configuration = script.wireguard.generate_config(server)
server.peers = []
server.sync(sess)
if len(peers) > 0:
server.from_db(sess)
for schemaPeer in peers:
schemaPeer.server_id = server.id
schemaPeer.configuration = script.wireguard.generate_config(dict(
peer=schemaPeer,
server=server
))
dbPeer = models.WGPeer(**schemaPeer.dict())
sess.add(dbPeer)
sess.commit()
server.configuration = script.wireguard.generate_config(server)
server.peers = []
server.sync(sess)
if len(peers) > 0:
server.from_db(sess)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
for schemaPeer in peers:
schemaPeer.server_id = server.id
schemaPeer.configuration = script.wireguard.generate_config(dict(
peer=schemaPeer,
server=server
))
dbPeer = models.WGPeer(**schemaPeer.dict())
sess.add(dbPeer)
sess.commit()
server.from_db(sess)
if start and not script.wireguard.is_running(server):
script.wireguard.start_interface(server)

21
wg-manager-backend/logger.py

@ -0,0 +1,21 @@
def setup_logging():
import logging
from loguru import logger
class InterceptHandler(logging.Handler):
def emit(self, record):
# Get corresponding Loguru level if it exists
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Find caller from where originated the logged message
frame, depth = logging.currentframe(), 2
while frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
logging.basicConfig(handlers=[InterceptHandler()], level=1)

11
wg-manager-backend/logging.json

@ -0,0 +1,11 @@
{
"logger": {
"path": "./logs",
"filename": "access.log",
"level": "info",
"rotation": "20 days",
"retention": "1 months",
"format": "<level>{level: <8}</level> <green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> {extra[request_id]} - <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>"
}
}

18
wg-manager-backend/main.py

@ -1,8 +1,14 @@
from logger import setup_logging
setup_logging()
import const
from uvicorn_loguru_integration import run_uvicorn_loguru
import time
from starlette.middleware.base import BaseHTTPMiddleware
import middleware
from routers.v1 import user, server, peer, wg
import script.wireguard_startup
import pkg_resources
@ -15,6 +21,7 @@ import database.util
app = FastAPI()
app.add_middleware(BaseHTTPMiddleware, dispatch=middleware.db_session_middleware)
app.add_middleware(BaseHTTPMiddleware, dispatch=middleware.logging_middleware)
app.include_router(
user.router,
@ -83,4 +90,13 @@ if __name__ == "__main__":
# Configure wireguard
script.wireguard_startup.setup_on_start()
uvicorn.run("__main__:app", reload=True)
run_uvicorn_loguru(
uvicorn.Config(
"__main__:app",
host="0.0.0.0",
port=8000,
log_level="warning",
reload=True,
workers=1
)
)

7
wg-manager-backend/middleware.py

@ -4,6 +4,7 @@ import jwt
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jwt import PyJWTError
from loguru import logger
from passlib.context import CryptContext
from sqlalchemy.orm import Session
from starlette import status
@ -27,6 +28,12 @@ def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
async def logging_middleware(request: Request, call_next):
response = await call_next(request)
logger.opt(depth=2).info(f"{request.method} {request.url} - Code: {response.status_code}")
return response
async def db_session_middleware(request: Request, call_next):
response = Response("Internal server error (Database error)", status_code=500)
try:

3
wg-manager-backend/migrations/env.py

@ -14,7 +14,8 @@ config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
if config.attributes.get('configure_logger', True):
fileConfig(config.config_file_name)
# add your model's MetaData object here
# for 'autogenerate' support

1
wg-manager-backend/requirements.txt

@ -13,6 +13,7 @@ sqlalchemy_utils
sqlalchemy-migrate
requests
uvicorn
uvicorn-loguru-integration
uvloop
httptools
qrcode[pil]

9
wg-manager-backend/util.py

@ -1,2 +1,11 @@
from loguru import logger
from fastapi import HTTPException
from jinja2 import Environment, PackageLoader
jinja_env = Environment(loader=PackageLoader(__name__, 'templates'))
class WGMHTTPException(HTTPException):
def __init__(self, status_code: int, detail: str = None):
HTTPException.__init__(self, status_code, detail)
logger.opt(depth=1).error(detail)
Loading…
Cancel
Save