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

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

@ -11,10 +11,9 @@ import script.wireguard
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from database import models from database import models
import schemas import schemas
import logging from loguru import logger
_LOGGER = logging.getLogger(__name__) from util import WGMHTTPException
_LOGGER.setLevel(logging.DEBUG)
def start_client(sess: Session, peer: schemas.WGPeer): 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. # Only add if it does not already exists.
server_add(schemas.WGServerAdd(**init_data), sess, start=const.SERVER_INIT_INTERFACE_START) server_add(schemas.WGServerAdd(**init_data), sess, start=const.SERVER_INIT_INTERFACE_START)
except Exception as e: except Exception as e:
_LOGGER.warning("Failed to setup initial server interface with exception:") logger.warning("Failed to setup initial server interface with exception:")
_LOGGER.exception(e) logger.exception(e)
def server_add(server: schemas.WGServerAdd, sess: Session, start=False): 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 [] peers = server.peers if server.peers else []
# Public/Private key all_interfaces = sess.query(models.WGServer).all()
try: 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) \ server.configuration = script.wireguard.generate_config(server)
.filter( server.peers = []
(models.WGServer.interface == server.interface) | server.sync(sess)
(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()
if len(peers) > 0:
server.from_db(sess) server.from_db(sess)
except ValueError as e: for schemaPeer in peers:
raise HTTPException(status_code=400, detail=str(e)) 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): if start and not script.wireguard.is_running(server):
script.wireguard.start_interface(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 import const
from uvicorn_loguru_integration import run_uvicorn_loguru
import time import time
from starlette.middleware.base import BaseHTTPMiddleware from starlette.middleware.base import BaseHTTPMiddleware
import middleware import middleware
from routers.v1 import user, server, peer, wg from routers.v1 import user, server, peer, wg
import script.wireguard_startup import script.wireguard_startup
import pkg_resources import pkg_resources
@ -15,6 +21,7 @@ import database.util
app = FastAPI() app = FastAPI()
app.add_middleware(BaseHTTPMiddleware, dispatch=middleware.db_session_middleware) app.add_middleware(BaseHTTPMiddleware, dispatch=middleware.db_session_middleware)
app.add_middleware(BaseHTTPMiddleware, dispatch=middleware.logging_middleware)
app.include_router( app.include_router(
user.router, user.router,
@ -83,4 +90,13 @@ if __name__ == "__main__":
# Configure wireguard # Configure wireguard
script.wireguard_startup.setup_on_start() 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 import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from jwt import PyJWTError from jwt import PyJWTError
from loguru import logger
from passlib.context import CryptContext from passlib.context import CryptContext
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from starlette import status from starlette import status
@ -27,6 +28,12 @@ def verify_password(plain_password, hashed_password):
return pwd_context.verify(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): async def db_session_middleware(request: Request, call_next):
response = Response("Internal server error (Database error)", status_code=500) response = Response("Internal server error (Database error)", status_code=500)
try: try:

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

@ -14,7 +14,8 @@ config = context.config
# Interpret the config file for Python logging. # Interpret the config file for Python logging.
# This line sets up loggers basically. # 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 # add your model's MetaData object here
# for 'autogenerate' support # for 'autogenerate' support

1
wg-manager-backend/requirements.txt

@ -13,6 +13,7 @@ sqlalchemy_utils
sqlalchemy-migrate sqlalchemy-migrate
requests requests
uvicorn uvicorn
uvicorn-loguru-integration
uvloop uvloop
httptools httptools
qrcode[pil] 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 from jinja2 import Environment, PackageLoader
jinja_env = Environment(loader=PackageLoader(__name__, 'templates')) 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