#!/usr/bin/env python

#----------------------------------------------------------------------
# Copyright (c) 2008 Board of Trustees, Princeton University
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS 
# IN THE WORK.
#----------------------------------------------------------------------

import os, sys
import traceback
import logging, logging.handlers

CRITICAL=logging.CRITICAL
ERROR=logging.ERROR
WARNING=logging.WARNING
INFO=logging.INFO
DEBUG=logging.DEBUG

# a logger that can handle tracebacks 
class Logger:
    def __init__ (self,logfile=None,loggername=None,level=logging.INFO):
        # default is to locate loggername from the logfile if avail.
        if not logfile:
            try:
                from planetstack.config import Config
                logfile = Config().observer_log_file
            except:
                logfile = "/var/log/planetstack.log"

        if (logfile == "console"):
            loggername = "console"
            handler = logging.StreamHandler()
        else:
            if not loggername:
                loggername=os.path.basename(logfile)
            try:
                handler=logging.handlers.RotatingFileHandler(logfile,maxBytes=1000000, backupCount=5)
            except IOError:
                # This is usually a permissions error becaue the file is
                # owned by root, but httpd is trying to access it.
                tmplogfile=os.getenv("TMPDIR", "/tmp") + os.path.sep + os.path.basename(logfile)
                # In strange uses, 2 users on same machine might use same code,
                # meaning they would clobber each others files
                # We could (a) rename the tmplogfile, or (b)
                # just log to the console in that case.
                # Here we default to the console.
                if os.path.exists(tmplogfile) and not os.access(tmplogfile,os.W_OK):
                    loggername = loggername + "-console"
                    handler = logging.StreamHandler()
                else:
                    handler=logging.handlers.RotatingFileHandler(tmplogfile,maxBytes=1000000, backupCount=5)

        handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
        self.logger=logging.getLogger(loggername)
        self.logger.setLevel(level)
        # check if logger already has the handler we're about to add
        handler_exists = False
        for l_handler in self.logger.handlers:
            if ((not hasattr(l_handler,"baseFilename")) or (l_handler.baseFilename == handler.baseFilename)) and \
               l_handler.level == handler.level:
                handler_exists = True 

        if not handler_exists:
            self.logger.addHandler(handler)

        self.loggername=loggername

    def setLevel(self,level):
        self.logger.setLevel(level)

    # shorthand to avoid having to import logging all over the place
    def setLevelDebug(self):
        self.logger.setLevel(logging.DEBUG)

    def debugEnabled (self):
        return self.logger.getEffectiveLevel() == logging.DEBUG

    # define a verbose option with s/t like
    # parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0)
    # and pass the coresponding options.verbose to this method to adjust level
    def setLevelFromOptVerbose(self,verbose):
        if verbose==0:
            self.logger.setLevel(logging.WARNING)
        elif verbose==1:
            self.logger.setLevel(logging.INFO)
        elif verbose>=2:
            self.logger.setLevel(logging.DEBUG)
    # in case some other code needs a boolean
    def getBoolVerboseFromOpt(self,verbose):
        return verbose>=1
    def getBoolDebugFromOpt(self,verbose):
        return verbose>=2

    ####################
    def info(self, msg):
        self.logger.info(msg)

    def debug(self, msg):
        self.logger.debug(msg)
        
    def warn(self, msg):
        self.logger.warn(msg)

    # some code is using logger.warn(), some is using logger.warning()
    def warning(self, msg):
        self.logger.warning(msg)
   
    def error(self, msg):
        self.logger.error(msg)    
 
    def critical(self, msg):
        self.logger.critical(msg)

    # logs an exception - use in an except statement
    def log_exc(self,message):
        self.error("%s BEG TRACEBACK"%message+"\n"+traceback.format_exc().strip("\n"))
        self.error("%s END TRACEBACK"%message)
    
    def log_exc_critical(self,message):
        self.critical("%s BEG TRACEBACK"%message+"\n"+traceback.format_exc().strip("\n"))
        self.critical("%s END TRACEBACK"%message)
    
    # for investigation purposes, can be placed anywhere
    def log_stack(self,message):
        to_log="".join(traceback.format_stack())
        self.info("%s BEG STACK"%message+"\n"+to_log)
        self.info("%s END STACK"%message)

    def enable_console(self, stream=sys.stdout):
        formatter = logging.Formatter("%(message)s")
        handler = logging.StreamHandler(stream)
        handler.setFormatter(formatter)
        self.logger.addHandler(handler)


info_logger = Logger(loggername='info', level=logging.INFO)
debug_logger = Logger(loggername='debug', level=logging.DEBUG)
warn_logger = Logger(loggername='warning', level=logging.WARNING)
error_logger = Logger(loggername='error', level=logging.ERROR)
critical_logger = Logger(loggername='critical', level=logging.CRITICAL)
logger = info_logger
########################################
import time

def profile(logger):
    """
    Prints the runtime of the specified callable. Use as a decorator, e.g.,
    
    @profile(logger)
    def foo(...):
        ...
    """
    def logger_profile(callable):
        def wrapper(*args, **kwds):
            start = time.time()
            result = callable(*args, **kwds)
            end = time.time()
            args = map(str, args)
            args += ["%s = %s" % (name, str(value)) for (name, value) in kwds.iteritems()]
            # should probably use debug, but then debug is not always enabled
            logger.info("PROFILED %s (%s): %.02f s" % (callable.__name__, ", ".join(args), end - start))
            return result
        return wrapper
    return logger_profile


if __name__ == '__main__': 
    print 'testing logging into logger.log'
    logger1=Logger('logger.log', loggername='std(info)')
    logger2=Logger('logger.log', loggername='error', level=logging.ERROR)
    logger3=Logger('logger.log', loggername='debug', level=logging.DEBUG)
    
    for (logger,msg) in [ (logger1,"std(info)"),(logger2,"error"),(logger3,"debug")]:
        
        print "====================",msg, logger.logger.handlers
   
        logger.enable_console()
        logger.critical("logger.critical")
        logger.error("logger.error")
        logger.warn("logger.warning")
        logger.info("logger.info")
        logger.debug("logger.debug")
        logger.setLevel(logging.DEBUG)
        logger.debug("logger.debug again")
    
        @profile(logger)
        def sleep(seconds = 1):
            time.sleep(seconds)

        logger.info('console.info')
        sleep(0.5)
        logger.setLevel(logging.DEBUG)
        sleep(0.25)

