classification
Title: Logger library with task scheduler
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: btjehunt, eric.smith, paul.moore, steve.dower, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2021-09-09 13:47 by btjehunt, last changed 2021-09-09 23:33 by steve.dower.

Messages (3)
msg401482 - (view) Author: Brian Hunt (btjehunt) Date: 2021-09-09 13:47
Version: Python 3.9.3
Package: Logger + Windows 10 Task Scheduler
Error Msg: None

Behavior:
I built a logging process to use with a python script that will be scheduled with Windows 10 task scheduler (this could be a bug in task scheduler too, but starting here). I noticed it wasn’t working and started trying to trace the root of the issue.

If I created a new file called scratch.py and ran some code, the logs showed up. However, the exact same code in the exact same folder (titled: run_xyz.py) didn’t log those same messages. It appears that something in either the task scheduler or logger library doesn’t like the fact that my file name contains an underscore because as soon as I pointed my task scheduler task that didn’t log to my other file, it worked again. Also, when I finally removed the underscores it started working. I believe it is Logger library related because the task with underscores does in fact run the python code and generate the script output.



Code in both files:
-----------------a_b_c.py code-----------
import os
import pathlib
import sys

pl_path = pathlib.Path(__file__).parents[1].resolve()
sys.path.append(str(pl_path))



from src.Core.Logging import get_logger
#
logger = get_logger(__name__, False)
logger.info("TESTING_USing taskScheduler")



-------src.Core.Logging.py get_logger code--------
import logging
import datetime
import time
import os

# from logging.handlers import SMTPHandler

from config import build_stage, log_config
from Pipelines.Databases import sqlAlchemy_logging_con


class DBHandler(logging.Handler):
    def __init__(self, name):
        """

        :param name: Deprecated
        """
        logging.StreamHandler.__init__(self)
        self.con = sqlAlchemy_logging_con()
        self.sql = """insert into Logs (LogMessage, Datetime, FullPathNM, LogLevelNM, ErrorLine) values ('{message}', '{dbtime}', '{pathname}', '{level}', '{errLn}')"""
        self.name = name



    def formatDBTime(self, record):
        record.dbtime = datetime.strftime("#%Y/%m/%d#", datetime.localtime(record.created))

    def emit(self, record):
        creation_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(record.created))

        try:
            self.format(record)

            if record.exc_info:
                record.exc_text = logging._defaultFormatter.formatException(record.exc_info)
            else:
                record.exc_text = ""

            sql = self.sql.format(message=record.message
                                  , dbtime=creation_time
                                  , pathname=record.pathname
                                  , level=record.levelname
                                  , errLn=record.lineno)

            self.con.execute(sql)




        except:
            pass


def get_logger(name, use_local_logging=False):
    """
    Returns a logger based on a name given. Name should be __name__ variable or unique for each call.
    Never call more than one time in a given file as it clears the logger. Use config.log_config to define configuration
    of the logger and its handlers.
    :param name:
    :return: logger
    """
    logger = logging.getLogger(name)
    logger.handlers.clear()

    # used to send logs to local file location. Level set to that of logger
    if use_local_logging:
        handler = logging.FileHandler("Data\\Output\\log_" + build_stage + str(datetime.date.today()).replace("-","") + ".log")
        handler.setLevel(log_config['logger_level'])
        logger.addHandler(handler)

    dbhandler = DBHandler(name)
    dbhandler.setLevel(log_config['db_handler_level'])
    logger.addHandler(dbhandler)
    logger.setLevel(log_config['logger_level'])



    return logger
msg401484 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-09-09 14:08
Can you simplify this to not use any external libraries?
msg401536 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2021-09-09 23:33
Also, can you include your full task definition? There are a lot of options there which could cause it to launch in a different working directory (which will mess with your relative paths) or as a different user (which could mess with whether you can import your libraries).

I think it's possible to export the task definition as XML. Copy/pasting that here will be fine (not as an attachment, please, we just need to read it).

It's also difficult to collect standard output, so you may want to try adding something like "sys.stdout = sys.stderr = open(r'C:\Users\Public\Public Documents\log.txt', 'w')" to try and collect any output that you may be missing. The full path to the file is important, and it will need to be somewhere that most accounts can write.
History
Date User Action Args
2021-09-09 23:33:28steve.dowersetmessages: + msg401536
2021-09-09 14:08:41eric.smithsetnosy: + eric.smith
messages: + msg401484
components: - Windows, IO
2021-09-09 13:47:28btjehuntcreate