[tarantino] r157 committed - Logging and email in BatchJobs

2 views
Skip to first unread message

codesite...@google.com

unread,
Feb 26, 2010, 5:57:03 PM2/26/10
to tarantino...@googlegroups.com
Revision: 157
Author: ajepst
Date: Fri Feb 26 14:56:10 2010
Log: Logging and email in BatchJobs
http://code.google.com/p/tarantino/source/detail?r=157

Added:
/trunk/src/BatchJobs.Console/Log4Net.config
/trunk/src/BatchJobs.Console/Logger.cs
Modified:
/trunk/src/BatchJobs.Console/App.config
/trunk/src/BatchJobs.Console/BatchJobs.Console.csproj
/trunk/src/BatchJobs.Console/Program.cs
/trunk/src/BatchJobs.Core/BatchJobs.Core.csproj
/trunk/src/BatchJobs.Core/JobAgentBase.cs

/trunk/src/Tarantino.Deployer.IntegrationTests/Tarantino.Deployer.IntegrationTests.csproj

=======================================
--- /dev/null
+++ /trunk/src/BatchJobs.Console/Log4Net.config Fri Feb 26 14:56:10 2010
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<log4net debug="false">
+ <appender name="RollingFileAppender"
type="log4net.Appender.RollingFileAppender">
+ <file value="Log/log4net.log" />
+ <appendToFile value="true" />
+ <rollingStyle value="Size" />
+ <maxSizeRollBackups value="10" />
+ <maximumFileSize value="1000KB" />
+ <staticLogFileName value="true" />
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%d [%t] %-5p %c - %m%n" />
+ </layout>
+ </appender>
+ <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%d [%t] %-5p %c - %m%n" />
+ </layout>
+ </appender>
+ <appender name="OutputDebugStringAppender"
type="log4net.Appender.OutputDebugStringAppender">
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%-5p %m - %c -%n" />
+ </layout>
+ </appender>
+ <appender name="FileAppender" type="log4net.Appender.FileAppender">
+ <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
+ <file value="Log/BatchRun.log" />
+ <appendToFile value="false" />
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%d [%t] %-5p %c - %m%n" />
+ </layout>
+ </appender>
+ <root>
+ <level value="DEBUG" />
+ <appender-ref ref="RollingFileAppender" />
+ <appender-ref ref="ConsoleAppender" />
+ <appender-ref ref="OutputDebugStringAppender" />
+ <appender-ref ref="FileAppender" />
+ </root>
+</log4net>
=======================================
--- /dev/null
+++ /trunk/src/BatchJobs.Console/Logger.cs Fri Feb 26 14:56:10 2010
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using log4net;
+using log4net.Config;
+
+namespace BatchJobs.Console
+{
+ public static class Logger
+ {
+ private static bool _logInitialized;
+ public const string CONFIG_FILE_NAME = "Log4Net.config";
+ private static readonly Dictionary<Type, ILog> _loggers = new
Dictionary<Type, ILog>();
+
+ private static void initialize()
+ {
+ XmlConfigurator.ConfigureAndWatch(new FileInfo(getConfigFilePath()));
+ }
+
+ private static string getConfigFilePath()
+ {
+ string basePath =
AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
+ string configPath = Path.Combine(basePath, CONFIG_FILE_NAME);
+
+ if (!File.Exists(configPath))
+ {
+ configPath = Path.Combine(basePath, "bin");
+ configPath = Path.Combine(configPath, CONFIG_FILE_NAME);
+
+ if (!File.Exists(configPath))
+ {
+ configPath = Path.Combine(basePath, @"..\" + CONFIG_FILE_NAME);
+ }
+ }
+
+ return configPath;
+ }
+
+ public static void EnsureInitialized()
+ {
+ if (!_logInitialized)
+ {
+ initialize();
+ _logInitialized = true;
+ }
+ }
+
+ public static string SerializeException(Exception e)
+ {
+ return serializeException(e, string.Empty);
+ }
+
+ private static string serializeException(Exception e, string
exceptionMessage)
+ {
+ if (e == null) return string.Empty;
+
+ exceptionMessage = string.Format(
+ "{0}{1}{2}\n{3}",
+ exceptionMessage,
+ (exceptionMessage == string.Empty) ? string.Empty : "\n\n",
+ e.Message,
+ e.StackTrace);
+
+ if (e.InnerException != null)
+ exceptionMessage = serializeException(e.InnerException,
exceptionMessage);
+
+ return exceptionMessage;
+ }
+
+ private static ILog getLogger(Type source)
+ {
+ if (!_loggers.ContainsKey(source))
+ {
+ lock(_loggers)
+ {
+ if (!_loggers.ContainsKey(source))
+ {
+ ILog logger = LogManager.GetLogger(source);
+ _loggers.Add(source, logger);
+ }
+ }
+ }
+
+
+ return _loggers[source];
+ }
+
+ public static void Debug(object source, object message)
+ {
+ Debug(source.GetType(), message);
+ }
+
+ public static void Debug(Type source, object message)
+ {
+ getLogger(source).Debug(message);
+ }
+
+ public static void Info(object source, object message)
+ {
+ Info(source.GetType(), message);
+ }
+
+ public static void Info(Type source, object message)
+ {
+ getLogger(source).Info(message);
+ }
+
+ public static void Warn(object source, object message)
+ {
+ Warn(source.GetType(), message);
+ }
+
+ public static void Warn(Type source, object message)
+ {
+ getLogger(source).Warn(message);
+ }
+
+ public static void Error(object source, object message)
+ {
+ Error(source.GetType(), message);
+ }
+
+ public static void Error(Type source, object message)
+ {
+ getLogger(source).Error(message);
+ }
+
+ public static void Fatal(object source, object message)
+ {
+ Fatal(source.GetType(), message);
+ }
+
+ public static void Fatal(Type source, object message)
+ {
+ getLogger(source).Fatal(message);
+ }
+
+ public static void Debug(object source, object message, Exception
exception)
+ {
+ Debug(source.GetType(), message, exception);
+ }
+
+ public static void Debug(Type source, object message, Exception
exception)
+ {
+ getLogger(source).Debug(message, exception);
+ }
+
+ public static void Info(object source, object message, Exception
exception)
+ {
+ Info(source.GetType(), message, exception);
+ }
+
+ public static void Info(Type source, object message, Exception exception)
+ {
+ getLogger(source).Info(message, exception);
+ }
+
+ public static void Warn(object source, object message, Exception
exception)
+ {
+ Warn(source.GetType(), message, exception);
+ }
+
+ public static void Warn(Type source, object message, Exception exception)
+ {
+ getLogger(source).Warn(message, exception);
+ }
+
+ public static void Error(object source, object message, Exception
exception)
+ {
+ Error(source.GetType(), message, exception);
+ }
+
+ public static void Error(Type source, object message, Exception
exception)
+ {
+ getLogger(source).Error(message, exception);
+ }
+
+ public static void Fatal(object source, object message, Exception
exception)
+ {
+ Fatal(source.GetType(), message, exception);
+ }
+
+ public static void Fatal(Type source, object message, Exception
exception)
+ {
+ getLogger(source).Fatal(message, exception);
+ }
+ }
+}
=======================================
--- /trunk/src/BatchJobs.Console/App.config Tue Dec 15 07:56:03 2009
+++ /trunk/src/BatchJobs.Console/App.config Fri Feb 26 14:56:10 2010
@@ -2,5 +2,9 @@
<configuration>
<appSettings>
<add key="JobAgentFactoryType"
value="BatchJobs.Console.DebugerJobAgentFactory, BatchJobs.Console"/>
+ <add key="BatchLogFileToEmail" value="aje...@gmail.com"/>
+ <add key="BatchLogFileFromEmail" value="an...@headspring.com"/>
+ <add key="BatchLogFileSmtpHost" value="localhost"/>
+ <add key="BatchLogFileLocation"
value="BatchJobs.Console\bin\Debug\Log\BatchRun.log" />
</appSettings>
</configuration>
=======================================
--- /trunk/src/BatchJobs.Console/BatchJobs.Console.csproj Wed Dec 9
12:00:36 2009
+++ /trunk/src/BatchJobs.Console/BatchJobs.Console.csproj Fri Feb 26
14:56:10 2010
@@ -12,6 +12,21 @@
<AssemblyName>BatchJobs.Console</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|
AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -31,6 +46,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral,
PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\NHibernate\1.2.1\log4net.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
@@ -46,6 +65,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Logger.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@@ -57,6 +77,41 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
+ <None Include="Log4Net.config">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the
targets below and uncomment it.
=======================================
--- /trunk/src/BatchJobs.Console/Program.cs Tue Dec 15 07:56:03 2009
+++ /trunk/src/BatchJobs.Console/Program.cs Fri Feb 26 14:56:10 2010
@@ -2,94 +2,154 @@
using System.Collections.Generic;
using System.Configuration;
using System.IO;
+using System.Net.Mail;
using System.Reflection;
using BatchJobs.Core;

namespace BatchJobs.Console
{
- public class Program
- {
- public const string JobagentfactorytypeKey = "JobAgentFactoryType";
-
- public Func<string> GetFactoryTypeName = () =>
ConfigurationManager.AppSettings[JobagentfactorytypeKey];
-
- private static void Main(string[] args)
- {
- try
- {
- new Program().Run(args);
- }
- catch (Exception e)
- {
- System.Console.WriteLine(e.Message);
- Environment.ExitCode = 100;
- }
- }
-
- public virtual void Run(string[] args)
- {
- if(args.Length==0)
- {
- System.Console.WriteLine("One of the following instance
names must be specified:");
- foreach(var name in Factory().GetInstanceNames())
- {
- System.Console.WriteLine(name);
- }
- }
- else
- {
- IJobAgent jobAgent = Factory().Create(args[0]);
- jobAgent.Execute();
- }
- }
-
- public virtual IJobAgentFactory Factory()
- {
- string typename = GetFactoryTypeName();
- string assemblyname;
-
- try
- {
- assemblyname = typename.Split(',')[1].Trim();
- typename = typename.Split(',')[0].Trim();
- }
- catch(Exception)
- {
- throw new InvalidOperationException("Could not parse the
typename from the application configuration.");
- }
-
- Assembly a = null;
- try
- {
- a = Assembly.Load(assemblyname);
- }
- catch (FileNotFoundException e)
- {
- System.Console.WriteLine(e.Message);
- }
- Type classType = a.GetType(typename);
- return (IJobAgentFactory) Activator.CreateInstance(classType);
- }
- }
- public class DebugerJobAgentFactory:IJobAgentFactory
- {
- public IJobAgent Create(string name)
- {
- System.Console.WriteLine(name);
- return new DebugerJobAgent();
- }
-
- public IEnumerable<string> GetInstanceNames()
- {
- return new string[]{"Foo","Bar"};
- }
- }
-
- public class DebugerJobAgent : IJobAgent
- {
- public void Execute()
- {
- System.Console.WriteLine("Executing");
- }
- }
-}
+ public class Program
+ {
+ public const string JobagentfactorytypeKey = "JobAgentFactoryType";
+
+ public Func<string> GetFactoryTypeName = () =>
ConfigurationManager.AppSettings[JobagentfactorytypeKey];
+
+ private static void Main(string[] args)
+ {
+ Logger.EnsureInitialized();
+ try
+ {
+ new Program().Run(args);
+ }
+ catch (Exception e)
+ {
+ System.Console.WriteLine(e.Message);
+ var sender = new LogFileToEmailSender();
+
+ sender.Send(string.Join(",", args));
+ Environment.ExitCode = 100;
+ }
+ }
+
+ public virtual void Run(string[] args)
+ {
+ if (args.Length == 0)
+ {
+ Logger.Fatal(this, "Command Line Instance Name Not Specified");
+ System.Console.WriteLine("One of the following instance names must be
specified:");
+ foreach (var name in Factory().GetInstanceNames())
+ {
+ System.Console.WriteLine(name);
+ }
+ }
+ else
+ {
+ Logger.Debug(this, string.Format("Command Line Specified Instance
Name: {0}", args[0]));
+ IJobAgent jobAgent = Factory().Create(args[0]);
+ Logger.Debug(this, "Executing the Job");
+ jobAgent.Execute();
+ }
+ }
+
+ public virtual IJobAgentFactory Factory()
+ {
+ string unparsedTypename = GetFactoryTypeName();
+ string typename;
+ string assemblyname;
+
+ try
+ {
+ Logger.Debug(this, string.Format("Parsing assembly and type names from
string \"{0}\"", unparsedTypename));
+ assemblyname = unparsedTypename.Split(',')[1].Trim();
+ typename = unparsedTypename.Split(',')[0].Trim();
+ }
+ catch (Exception)
+ {
+ Logger.Fatal(this, String.Format("Could not parse the typename from
the application configuration. configuration value: \"{0}\", configuration
key: \"{1}\"", unparsedTypename, JobagentfactorytypeKey));
+ throw new InvalidOperationException("Could not parse the typename from
the application configuration.");
+ }
+
+ Assembly a = null;
+ try
+ {
+ Logger.Debug(this, string.Format("Loading Assembly {0}",
assemblyname));
+ a = Assembly.Load(assemblyname);
+ }
+ catch (FileNotFoundException e)
+ {
+ Logger.Fatal(this, string.Format("Unable to load assembly {0}",
assemblyname));
+ System.Console.WriteLine(e.Message);
+ }
+ Type classType = a.GetType(typename);
+ Logger.Debug(this, string.Format("Creating instance of {0}",
classType));
+ return (IJobAgentFactory)Activator.CreateInstance(classType);
+ }
+ }
+
+ public class DebugerJobAgentFactory : IJobAgentFactory
+ {
+ public IJobAgent Create(string name)
+ {
+ System.Console.WriteLine(name);
+ return new DebugerJobAgent();
+ }
+
+ public IEnumerable<string> GetInstanceNames()
+ {
+ return new string[] { "Foo", "Bar" };
+ }
+ }
+
+ public class DebugerJobAgent : IJobAgent
+ {
+ public void Execute()
+ {
+ System.Console.WriteLine("Executing");
+ }
+ }
+
+ public class LogFileToEmailSender
+ {
+ private const string ToEmailKey = "BatchLogFileToEmail";
+ private const string FromEmailKey = "BatchLogFileFromEmail";
+ private const string SmtpHostKey = "BatchLogFileSmtpHost";
+ private const string FileLocationKey = "BatchLogFileLocation";
+
+ public Func<string> GetToEmail = () =>
ConfigurationManager.AppSettings[ToEmailKey];
+ public Func<string> GetFromEmail = () =>
ConfigurationManager.AppSettings[FromEmailKey];
+ public Func<string> GetSmtpHost = () =>
ConfigurationManager.AppSettings[SmtpHostKey];
+ public Func<string> GetFileLocation = () =>
ConfigurationManager.AppSettings[FileLocationKey];
+
+
+ public void Send(string args)
+ {
+ var message = CreateMessage(args);
+ var client = new SmtpClient { Host = GetSmtpHost() };
+ client.Send(message);
+ }
+
+ public MailMessage CreateMessage(string args)
+ {
+ var message = new MailMessage(GetFromEmail(), GetToEmail())
+ {
+ Subject = String.Format("[{0}] Error on Batch Job",
args),
+ Body = GetFileText()
+ };
+ return message;
+ }
+
+ public string GetFileText()
+ {
+ using (FileStream fs = new FileStream(GetFileLocation(), FileMode.Open,
FileAccess.Read))
+ {
+ using (StreamReader sr = new StreamReader(fs))
+ {
+
+ return sr.ReadToEnd();
+ }
+ }
+ }
+ }
+
+
+}
=======================================
--- /trunk/src/BatchJobs.Core/BatchJobs.Core.csproj Wed Dec 9 12:00:36 2009
+++ /trunk/src/BatchJobs.Core/BatchJobs.Core.csproj Fri Feb 26 14:56:10 2010
@@ -52,6 +52,12 @@
<Compile Include="IStateTransition.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Tarantino.Core\Tarantino.Core.csproj">
+ <Project>{3F02EEBD-5B3B-4C5F-B2E7-4F5DFF6B3F03}</Project>
+ <Name>Tarantino.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the
targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
=======================================
--- /trunk/src/BatchJobs.Core/JobAgentBase.cs Wed Dec 9 12:00:36 2009
+++ /trunk/src/BatchJobs.Core/JobAgentBase.cs Fri Feb 26 14:56:10 2010
@@ -1,4 +1,6 @@
+using System;
using System.Collections.Generic;
+using Tarantino.Core.Commons.Services.Logging;

namespace BatchJobs.Core
{
@@ -13,15 +15,29 @@

public void Execute()
{
+ Logger.Debug(this, "Getting transitions");
IEnumerable<IStateTransition<T>> transitions =
_factory.GetAll<T>();
+ Logger.Debug(this, "Retrieved transitions");
T[] batches = GetNextEntites();
+ Logger.Debug(this, string.Format("Found {0} batches", batches.Length));

foreach (T batch in batches)
{
foreach (var transition in transitions)
{
- if (transition.IsValid(batch))
- transition.Execute(batch);
+ Logger.Debug(this, string.Format("Examining transition {0} in batch
{1}", transition, batch));
+ if (transition.IsValid(batch))
+ {
+ Logger.Debug(this, string.Format("Transition {0} is valid for batch
{1}, executing", transition, batch));
+ try
+ {
+ transition.Execute(batch);
+ } catch(Exception e)
+ {
+ Logger.Fatal(this, Logger.SerializeException(e));
+ throw;
+ }
+ }
}
}
}
=======================================
---
/trunk/src/Tarantino.Deployer.IntegrationTests/Tarantino.Deployer.IntegrationTests.csproj
Tue Dec 29 12:09:43 2009
+++
/trunk/src/Tarantino.Deployer.IntegrationTests/Tarantino.Deployer.IntegrationTests.csproj
Fri Feb 26 14:56:10 2010
@@ -58,8 +58,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Core\Model\DeploymentTester.cs" />
- <Compile
Include="Core\Services\Configuration\ApplicationRepositoryTester.cs" />
<Compile Include="Infrastructure\DataAccess\DeployerDatabaseTester.cs"
/>
<Compile
Include="Infrastructure\DataAccess\Mappings\DeploymentMappingsTester.cs" />
<Compile
Include="Infrastructure\DataAccess\Repositories\DeploymentRepositoryTester.cs"
/>

Reply all
Reply to author
Forward
0 new messages