Commit 70da5a96 authored by Trevor Cappallo's avatar Trevor Cappallo
Browse files

fork from BTS/Lightning

parents
#!/usr/local/CentOS5/bin/python2.7
import sys,os,pwd
import logging,itertools
import subprocess
import socket
import tempfile
import atexit
import OperationalMail
import ProjectConfiguration
import datetime
import StringIO
def __exitHandler(logger,addresses,critical_addresses) :
if ProjectConfiguration.ProjectConfiguration.isServerOperational() :
if logger.hasCritical() :
addresses = list(set([a for a in itertools.chain(addresses,
critical_addresses)]))
if not logger.hasErrors() :
logging.info('No errors found. Email not sent')
else :
if not addresses :
logging.warning('No recipients found. Email not sent')
else :
logger.emailLog(addresses)
class OperationalLogger :
def __init__(self,log_file='log.txt',log_level=logging.DEBUG) :
self.__file_name = log_file
self.__server_name = socket.gethostbyaddr(socket.gethostname())[0]
self.__full_buffer = StringIO.StringIO()
self.__error_buffer = StringIO.StringIO()
self.__critical_buffer = StringIO.StringIO()
logging.basicConfig(filename=log_file,
format='[%(asctime)s][%(levelname)s][p%(process)d][%(filename)s:%(lineno)d]:%(message)s',
datefmt='%Y/%m/%d %H:%M:%S',
level=log_level)
formatter = logging.Formatter(fmt='[%(asctime)s][%(levelname)s][p%(process)d][%(filename)s:%(lineno)d]:%(message)s',
datefmt='%m/%d %H:%M:%S')
full_trigger = logging.StreamHandler(self.__full_buffer)
full_trigger.setLevel(logging.DEBUG)
full_trigger.setFormatter(formatter)
error_trigger = logging.StreamHandler(self.__error_buffer)
error_trigger.setLevel(logging.ERROR)
error_trigger.setFormatter(formatter)
critical_trigger = logging.StreamHandler(self.__critical_buffer)
critical_trigger.setLevel(logging.CRITICAL)
critical_trigger.setFormatter(formatter)
logging.getLogger('').addHandler(error_trigger)
logging.getLogger('').addHandler(critical_trigger)
logging.getLogger('').addHandler(full_trigger)
if sys.stdout.isatty() :
console = logging.StreamHandler(sys.stdout)
console.setLevel(logging.DEBUG)
console.setFormatter(logging.Formatter(fmt='[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d]:%(message)s',
datefmt='%m/%d %H:%M:%S'))
logging.getLogger('').addHandler(console)
def hasErrors(self) :
return len(self.__error_buffer.getvalue()) > 0
def hasCritical(self) :
return len(self.__critical_buffer.getvalue()) > 0
def emailLog(self,addresses) :
message = "<br />\n".join([OperationalLogger.__colorize(l) for l in self.__error_buffer.getvalue().split('\n')])
OperationalMail.sendStatus('Errors detected {0}:{1}'.format(self.__server_name,
os.path.basename(sys.argv[0])),
addresses, message,
text_attachment=self.__full_buffer.getvalue())
@staticmethod
def __colorize(line) :
if '[CRITICAL]' in line :
return '<span style="color:red">{0}</span>'.format(line)
if '[ERROR]' in line :
return '<span style="color:red">{0}</span>'.format(line)
if '[WARNING]' in line :
return '<span style="color:blue">{0}</span>'.format(line)
return line
##########################################################################################
#
# Helper functions
#
##########################################################################################
def defaultLogging(log_file_name = None,
addresses = ProjectConfiguration.ProjectConfiguration.defaultRecipients(),
critical_addresses = ProjectConfiguration.ProjectConfiguration.operationsAddresses(),
) :
'''Set an intelligent,context-dependent
default logging scheme for the current script.'''
if not log_file_name :
log_file_name = os.path.basename(sys.argv[0])
log_directory = os.path.join(ProjectConfiguration.ProjectConfiguration.projectRoot(),
'log', datetime.datetime.utcnow().strftime('%Y-%m-%d'))
if not os.path.exists(log_directory) :
try :
os.makedirs(log_directory,0755)
except Exception,e:
# Potential race condition. Warn, but do not error
logging.warning('Unable to create log directory {0}:{1}'.format(log_directory,
str(e)))
logger = OperationalLogger(os.path.join(log_directory,'{0}.log'.format(log_file_name)),
logging.DEBUG)
logging.info('Logging output from: {0}'.format(' '.join(sys.argv)))
logging.info('Process id {0}, parent process id {1}'.format(os.getpid(),
os.getppid()))
logging.info('-' * 60)
if addresses and not sys.stdout.isatty() :
atexit.register(__exitHandler,logger,addresses,critical_addresses)
return
def longLog(logging_level=logging.INFO,
message='') :
''' For program output, multi-line messages, etc. '''
message_list = message.split("\n")
for msg in message_list :
logging.log(logging_level,msg)
return
def longCritical(message) :
longLog(logging.CRITICAL,message)
def longError(message) :
longLog(logging.ERROR,message)
def longWarning(message) :
longLog(logging.WARNING,message)
def longInfo(message) :
longLog(logging.INFO,message)
def longDebug(message) :
longLog(logging.DEBUG,message)
def loggedSubprocess(arg_list) :
logging.info('Child process of [p{0}]'.format(os.getppid()))
logging.info('Attempting {0}'.format(' '.join(arg_list)))
try :
results = subprocess.check_output(arg_list,stderr=subprocess.STDOUT)
except subprocess.CalledProcessError,cpe :
logging.error('Call {0} failed with exit code {1}'.format(' '.join(arg_list),
str(cpe.returncode)))
longError(cpe.output)
except Exception,e:
logging.error('Unknown exception resulting from {0}:{1}'.format(' '.join(arg_list),
str(e)))
else :
logging.info('Successfully completed {0}'.format(' '.join(arg_list)))
longInfo(results)
return 0
logging.warning('Failure on {0}'.format(' '.join(arg_list)))
return -1
def stackTrace(logging_level=logging.ERROR) :
import traceback
tb = traceback.format_exc()
longLog(logging_level,tb)
return
if __name__ == '__main__' :
defaultLogging('basic_unit_test.foo.bar',addresses=['emhughes@aer.com'])
test = ''' Blah
foo
bar
beer
bear
'''
logging.info('Blah')
logging.debug('Fin')
logging.error('An error in testing, oh, no!!')
logging.critical('Put up the Jimsignal!')
longError(test)
try :
beer_hat
except Exception,e:
logging.debug(str(e))
stackTrace(logging.ERROR)
mport sys,os,datetime,re
import smtplib,codecs
import logging
import ProjectConfiguration
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def sendStatus(subject, to_list, message,
from_address=ProjectConfiguration.ProjectConfiguration.mailSender(),
password=None, text_attachment=None,
**kargs) :
'''Send an email message to a given recipient list.'''
mail = MIMEMultipart('mixed')
mail['From'] = from_address
mail['Subject'] = subject
mail['To'] = ', '.join(to_list)
mail['Reply-To'] = 'no-reply@aer.com'
for key,value in kargs.iteritems() :
mail[key] = value
''' TODO: Efficient method of stripping Unicode?'''
try :
import html2text
final_text = html2text.html2text(message)
except Exception,e:
logging.warning('Unable to generate text version of email: {0}'.format(str(e)))
final_text = 'HTML ONLY'
contentPart = MIMEMultipart('alternative')
contentPart.attach(MIMEText(final_text, 'plain'))
contentPart.attach(MIMEText(message, 'html'))
mail.attach(contentPart)
if text_attachment :
attachment = None
if os.path.exists(text_attachment) :
attachment = MIMEText(file(text_attachment).read())
else :
attachment = MIMEText(text_attachment)
attachment.add_header('Content-Disposition',
'attachment',
filename='full_log.txt')
mail.attach(attachment)
server = smtplib.SMTP('smtp.aer.com')
if password :
user_name = from_address.partition('@')[0]
try :
server.login(user_name,password)
except Exception, e:
logging.error('Unable to log in to smtp server: {0}'.format(str(e)))
raise e
server.sendmail(from_address,to_list,mail.as_string())
server.quit()
return
if __name__ == '__main__' :
msg = '''<P>Test of the OperationalMail module</P>
<P>Let us see if this works.</P>
<UL>
<LI>I am not sure it should</LI>
<LI>Do I really want it to?</LI>
<LI>So many questions.</LI>
</UL>
<P>Fin</P>
'''
default_addresses = ProjectConfiguration.ProjectConfiguration.developerEmails()
sendStatus('Non-pyProcess Email Module', default_addresses,
msg)
#!/usr/local/CentOS5/bin/python2.7
import sys,os,re,logging
import itertools,datetime,re
not_blank = re.compile(r'\S')
def addressDirectory(file_name) :
return os.path.join(ProjectConfiguration.projectRoot(),
'project_config',
file_name)
def addressesFromFile(file_name) :
addresses = list()
# Allow errors to flow up
with open(file_name,'r') as mailing_list :
addresses = ''.join(mailing_list.readlines()).split(',')
addresses = [a.strip() for a in addresses if not_blank.search(a)]
return addresses
class ProjectConfiguration :
'''Currently a dummy file for project configuration settings'''
def __init__(self) :
pass
@staticmethod
def projectRoot() :
''' Root directory for the project.
Used mainly for log files and library path location. '''
return os.path.abspath(os.path.dirname(sys.argv[0]))
@staticmethod
def operationsAddresses() :
return addressesFromFile(addressDirectory('operations_management_email.txt'))
@staticmethod
def defaultRecipients() :
return addressesFromFile(addressDirectory('developers_email.txt'))
@staticmethod
def sysAdminsAddresses() :
return addressesFromFile(addressDirectory('is_email.txt'))
@staticmethod
def mailSender() :
return 'lightning_slurp@aer.com'
@staticmethod
def isServerOperational() :
return True
if __name__ == '__main__' :
''' Nothing worth testing yet. '''
pass
Logging for Operations.
Originally forked from BTS/Lightning on 05-Aug-2015.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment