commit
3dd8bdc669
9 changed files with 313 additions and 0 deletions
@ -0,0 +1,24 @@ |
|||||||
|
import yaml |
||||||
|
import json |
||||||
|
import logging |
||||||
|
|
||||||
|
logger = logging.getLogger("fds") |
||||||
|
|
||||||
|
class Config(): |
||||||
|
def __init__(self, config_file: str): |
||||||
|
with open(config_file, "r") as cfile: |
||||||
|
self.__dict__ = yaml.safe_load(cfile) |
||||||
|
self.set_params(self.__dict__) |
||||||
|
|
||||||
|
def set_params(self, config: dict): |
||||||
|
for k, v in config.items(): |
||||||
|
# if type(v) is dict: |
||||||
|
# set_params(v) |
||||||
|
setattr(self, k, v) |
||||||
|
|
||||||
|
def __repr__(self): |
||||||
|
return json.dumps(self.__dict__, indent=4) |
||||||
|
|
||||||
|
class LogConfig(Config): |
||||||
|
... |
||||||
|
|
||||||
@ -0,0 +1,79 @@ |
|||||||
|
import os |
||||||
|
import logging |
||||||
|
from logging.handlers import RotatingFileHandler |
||||||
|
|
||||||
|
# COLORED_FORMAT = '%(asctime)-15s [%(levelname)s] %(threadName)-12s ' |
||||||
|
# NORMAL_FORMAT = '%(filename)s %(funcName)s, line %(lineno)s: %(message)s' |
||||||
|
COLORED_FORMAT = '[%(levelname)s] %(threadName)-12s ' |
||||||
|
NORMAL_FORMAT = '%(message)s' # '%(filename)s %(funcName)s, line %(lineno)s: %(message)s' |
||||||
|
FORMAT = COLORED_FORMAT + NORMAL_FORMAT |
||||||
|
|
||||||
|
class ColoredFormatter(logging.Formatter): |
||||||
|
|
||||||
|
grey = "\x1b[38;20m" |
||||||
|
yellow = "\x1b[33;20m" |
||||||
|
red = "\x1b[31;20m" |
||||||
|
bold_red = "\x1b[31;1m" |
||||||
|
white = "\x1b[33;97m" |
||||||
|
green = "\x1b[33;92m" |
||||||
|
reset = "\x1b[0m" |
||||||
|
|
||||||
|
FORMATS = { |
||||||
|
logging.DEBUG: white + COLORED_FORMAT + reset + NORMAL_FORMAT, |
||||||
|
logging.INFO: green + COLORED_FORMAT + reset + NORMAL_FORMAT, |
||||||
|
logging.WARNING: yellow + COLORED_FORMAT + reset + NORMAL_FORMAT, |
||||||
|
logging.ERROR: red + COLORED_FORMAT + reset + NORMAL_FORMAT, |
||||||
|
logging.CRITICAL: bold_red + COLORED_FORMAT + reset + NORMAL_FORMAT |
||||||
|
} |
||||||
|
|
||||||
|
def format(self, record): |
||||||
|
log_fmt = self.FORMATS.get(record.levelno) |
||||||
|
formatter = logging.Formatter(log_fmt, datefmt='%Y-%m-%d %I:%M:%S%p') |
||||||
|
return formatter.format(record) |
||||||
|
|
||||||
|
def set_log_folder(path: str): |
||||||
|
dir = os.path.dirname(path) |
||||||
|
if len(dir) == 0: |
||||||
|
dir = "./" |
||||||
|
|
||||||
|
os.makedirs(dir, exist_ok=True) |
||||||
|
|
||||||
|
def set_logger(name: str = "fds", filename: str = "main.log", level: str = "info", logtest=False): |
||||||
|
set_log_folder(filename) |
||||||
|
logging_levels = ( |
||||||
|
logging.CRITICAL, |
||||||
|
logging.ERROR, |
||||||
|
logging.WARNING, |
||||||
|
logging.INFO, |
||||||
|
logging.DEBUG, |
||||||
|
) |
||||||
|
log_level = getattr(logging, level.upper()) |
||||||
|
|
||||||
|
assert log_level in logging_levels |
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(name) |
||||||
|
log.setLevel(log_level) |
||||||
|
|
||||||
|
file_handler = RotatingFileHandler(filename, maxBytes=100000000, backupCount=10) |
||||||
|
file_handler.setLevel(logging.DEBUG) |
||||||
|
file_handler.setFormatter(logging.Formatter(FORMAT)) |
||||||
|
log.addHandler(file_handler) |
||||||
|
|
||||||
|
stream_handler = logging.StreamHandler() |
||||||
|
# stream_handler.setLevel(log_level) |
||||||
|
stream_handler.setLevel(logging.DEBUG) |
||||||
|
stream_handler.setFormatter(ColoredFormatter()) |
||||||
|
log.addHandler(stream_handler) |
||||||
|
|
||||||
|
if logtest: |
||||||
|
t_log = getattr(log, level) |
||||||
|
t_log(f"Logging level: {level.upper()}") |
||||||
|
log.info("You can see below log labels") |
||||||
|
log.debug("DEBUG level") |
||||||
|
log.info("INFO level") |
||||||
|
log.warning("WARNING level") |
||||||
|
log.error("ERROR level") |
||||||
|
log.critical("CRITICAL level") |
||||||
|
|
||||||
|
return log |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
Config: |
||||||
|
- name: ttyUSB2 |
||||||
|
device: /dev/ttyUSB2 |
||||||
|
baudrate: 115200 |
||||||
|
- name: ttyUSB1 |
||||||
|
device: /dev/ttyUSB1 |
||||||
|
baudrate: 115200 |
||||||
|
- name: ttyUSB3 |
||||||
|
device: /dev/ttyUSB3 |
||||||
|
baudrate: 115200 |
||||||
@ -0,0 +1,140 @@ |
|||||||
|
import os |
||||||
|
import sys |
||||||
|
import json |
||||||
|
import serial |
||||||
|
import signal |
||||||
|
import logging |
||||||
|
import argparse |
||||||
|
from threading import Thread |
||||||
|
from contextlib import contextmanager, ExitStack |
||||||
|
from signal import SIGINT, SIGTERM |
||||||
|
from serial.tools import list_ports |
||||||
|
from datetime import datetime as dt |
||||||
|
|
||||||
|
from lib.logger import set_logger |
||||||
|
from lib.config import LogConfig |
||||||
|
|
||||||
|
|
||||||
|
def parsing_argument(): |
||||||
|
parser = argparse.ArgumentParser(description="USB-UART Serial logging.") |
||||||
|
# parser.add_argument('-p', '--serial-path', type=str, default="/dev/ttyUSB2", help="Path to device file") |
||||||
|
# parser.add_argument('-b', '--baudrate', type=int, default=115200, help="Baudrate") |
||||||
|
parser.add_argument('-f', '--log-file', type=str, default="logs/main.log", help="Name of log file") |
||||||
|
parser.add_argument('-d', '--log-level', type=str, default="info", choices=['notset', 'info', 'debug', 'warning', 'error', 'critical'], help="Set log level") |
||||||
|
parser.add_argument('-c', '--log-config', type=str, default="log-config.yml", help="Config for logging") |
||||||
|
args = parser.parse_args() |
||||||
|
# device = os.path.basename(args.serial_path) |
||||||
|
# if len(args.log_file) == 0: |
||||||
|
# args.log_file = f"{device}.log" |
||||||
|
return args |
||||||
|
|
||||||
|
class SerialLogger(): |
||||||
|
def __init__(self, config): |
||||||
|
self.set_params(config) |
||||||
|
# self.name = |
||||||
|
if not hasattr(self, 'log_file') or len(self.log_file) == 0: |
||||||
|
self.log_file = f"logs/{self.name}.log" |
||||||
|
if not hasattr(self, 'log_level'): |
||||||
|
self.log_level='info' |
||||||
|
|
||||||
|
self.logger = set_logger(name=self.name, filename=self.log_file, level=self.log_level) |
||||||
|
|
||||||
|
self.stop=False |
||||||
|
|
||||||
|
print("") |
||||||
|
self.logger.info("-----------------------------------------------") |
||||||
|
self.logger.info(f"Logger launched {dt.now().strftime('%Y/%m/%d %a %H:%M:%S')}") |
||||||
|
self.logger.info(f"Target device: {self.device}, Baudrate: {self.baudrate}") |
||||||
|
self.logger.info(f"Log level: {self.log_level.upper()}, saved in \'{self.log_file}\'") |
||||||
|
self.logger.info("-----------------------------------------------\n") |
||||||
|
|
||||||
|
def set_params(self, config: dict): |
||||||
|
for k, v in config.items(): |
||||||
|
# if type(v) is dict: |
||||||
|
# set_params(v) |
||||||
|
setattr(self, k, v) |
||||||
|
|
||||||
|
@contextmanager |
||||||
|
def run(self): |
||||||
|
thread = Thread(target=self.listen, name=f"{self.name}") |
||||||
|
thread.start() |
||||||
|
try: |
||||||
|
yield |
||||||
|
finally: |
||||||
|
self.stop = True |
||||||
|
thread.join() |
||||||
|
|
||||||
|
def listen(self): |
||||||
|
tmp="" |
||||||
|
with serial.Serial(self.device, self.baudrate) as dev: |
||||||
|
while not self.stop: |
||||||
|
data = dev.readline(dev.inWaiting()).decode("latin1") |
||||||
|
if data: |
||||||
|
if "Ramdisk addr" in data: |
||||||
|
self.logger.info("") |
||||||
|
self.logger.info("-----------------------------------------") |
||||||
|
self.logger.info(f"FPGA Initialized. {dt.now().strftime('%Y/%m/%d %a %H:%M:%S')}") |
||||||
|
self.logger.info("-----------------------------------------") |
||||||
|
if data[-1] == '\n': |
||||||
|
tmp += data.strip() |
||||||
|
self.logger.info(tmp) |
||||||
|
tmp = "" |
||||||
|
else: |
||||||
|
tmp+= data.strip() |
||||||
|
|
||||||
|
#self.logger.info(data.strip()) |
||||||
|
|
||||||
|
|
||||||
|
def main(args=None): |
||||||
|
LOG = set_logger(filename=args.log_file, level=args.log_level) |
||||||
|
LOG.info("-----------------------------------------------") |
||||||
|
LOG.info(f"Logger launched {dt.now().strftime('%Y/%m/%d %a %H:%M:%S')}") |
||||||
|
LOG.info(f"Logging configs: {args.log_config}") |
||||||
|
LOG.info(f"Log level: {args.log_level.upper()}, saved in \'{args.log_file}\'") |
||||||
|
LOG.info("-----------------------------------------------\n") |
||||||
|
|
||||||
|
LOG.info("Available ports") |
||||||
|
for i, p in enumerate(list_ports.comports()): |
||||||
|
LOG.info(f"{i+1}) Deivce: {p.device}") |
||||||
|
LOG.info(f"\tDescription : {p.description}") |
||||||
|
LOG.info(f"\tHWID : {p.hwid}") |
||||||
|
LOG.info(f"\tSerial # : {p.serial_number}") |
||||||
|
LOG.info(f"\tLocation : {p.location}") |
||||||
|
LOG.info(f"\tManufacturer : {p.manufacturer}") |
||||||
|
LOG.info(f"\tProduct : {p.product}") |
||||||
|
LOG.info(f"\tInterface : {p.interface}\n") |
||||||
|
|
||||||
|
|
||||||
|
def signal_handler(sig, frame): |
||||||
|
sign = signal.Signals(sig) |
||||||
|
print("") |
||||||
|
LOG.info(f"Stop program by {signal.strsignal(sign)} ({sign.name})\n") |
||||||
|
|
||||||
|
configs = LogConfig(args.log_config).Config |
||||||
|
with ExitStack() as stack: |
||||||
|
for cfg in configs: |
||||||
|
LOG.info(f"Logging config:\n{json.dumps(cfg, indent=4)}") |
||||||
|
sl = SerialLogger(cfg) |
||||||
|
stack.enter_context(sl.run()) |
||||||
|
signal.signal(SIGINT, signal_handler) |
||||||
|
signal.signal(SIGTERM, signal_handler) |
||||||
|
print('\t To terminate the program, press Ctrl-c\n') |
||||||
|
signal.pause() |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0 |
||||||
|
|
||||||
|
|
||||||
|
def test(): |
||||||
|
config = LogConfig("log-config.yml") |
||||||
|
print(type(config.Config[0])) |
||||||
|
pass |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
# test() |
||||||
|
sys.exit( |
||||||
|
main(parsing_argument()) |
||||||
|
) |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
[Unit] |
||||||
|
Description=Python Serial Logger |
||||||
|
|
||||||
|
[Service] |
||||||
|
Type=simple |
||||||
|
WorkingDirectory=/home/fds-l1/Work/NVMe_Test/chaeeon.dev/sw |
||||||
|
ExecStart=/home/fds-l1/Work/NVMe_Test/chaeeon.dev/sw/python/peta-venv/bin/python /home/fds-l1/Work/NVMe_Test/chaeeon.dev/sw/python/pyLogger.py --log-config /home/fds-l1/Work/NVMe_Test/chaeeon.dev/sw/python/log-config.yml |
||||||
|
|
||||||
|
[Install] |
||||||
|
WantedBy=multi-user.target |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DEVICE_NUM=${1:-"2"} |
||||||
|
DEVICE=ttyUSB${DEVICE_NUM} |
||||||
|
DEVICE_FILE=/dev/${DEVICE} |
||||||
|
BAUDRATE=115200 |
||||||
|
LOGDIR=logs |
||||||
|
LOGFILE=${LOGDIR}/${DEVICE}.log |
||||||
|
|
||||||
|
TAG=${2:-"None"} |
||||||
|
|
||||||
|
log_message() { |
||||||
|
msg=${1:-""} |
||||||
|
echo ${msg} >> ${LOGFILE} |
||||||
|
} |
||||||
|
|
||||||
|
launch_message() { |
||||||
|
log_message |
||||||
|
log_message "-----------------------------" |
||||||
|
log_message " Logging launched: $(date)" |
||||||
|
log_message " Get logs from \'${DEVICE_FILE}\'" |
||||||
|
log_message " Logfile saved at \'${LOGFILE}\'" |
||||||
|
log_message " TAG: ${TAG}" |
||||||
|
log_message "-----------------------------" |
||||||
|
} |
||||||
|
|
||||||
|
old_main() { |
||||||
|
launch_message |
||||||
|
|
||||||
|
sudo screen -L -Logfile ${LOGFILE} ${DEVICE_FILE} ${BAUDRATE} |
||||||
|
sudo chown $USER:$USER ${LOGFILE} |
||||||
|
|
||||||
|
log_message |
||||||
|
log_message |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
main() { |
||||||
|
sudo python3 python/pyLogger.py --log-config python/log-config.yml |
||||||
|
} |
||||||
|
|
||||||
|
main |
||||||
Loading…
Reference in new issue