Updated logging and instrumentation

pull/7/merge
Keivan 14 years ago
parent b59d9f13b1
commit c597363bf8

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
IIS configuration sections.
@ -135,8 +135,8 @@
<add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
<add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />-->
<add name="IISExpressAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
<applicationPoolDefaults managedRuntimeLoader="v4.0" >
<processModel/>
<applicationPoolDefaults managedRuntimeLoader="v4.0">
<processModel />
</applicationPoolDefaults>
</applicationPools>
@ -156,7 +156,7 @@
<virtualDirectory path="/" physicalPath="%NZBDRONE_PATH%\NZBDrone.Web" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:8080:" />
<binding protocol="http" bindingInformation="*:8981:" />
</bindings>
</site>
<siteDefaults>

@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test
[SetUp]
public void Setup()
{
CentralDispatch.ConfigureNlog();
Instrumentation.Setup();
}
}
}

@ -29,7 +29,7 @@ namespace NzbDrone.Core
string connectionString = String.Format("Data Source={0};Version=3;", Path.Combine(AppPath, "nzbdrone.db"));
var provider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
provider.Log = new SonicTrace();
provider.Log = new Instrumentation.NlogWriter();
provider.LogParams = true;
_kernel.Bind<ISeriesProvider>().To<SeriesProvider>().InSingletonScope();
@ -62,60 +62,14 @@ namespace NzbDrone.Core
{
get
{
if (_kernel == null)
{
BindKernel();
}
return _kernel;
}
}
public static void ConfigureNlog()
{
// Step 1. Create configuration object
var config = new LoggingConfiguration();
string callSight = "${callsite:className=false:fileName=true:includeSourcePath=false:methodName=true}";
// Step 2. Create targets and add them to the configuration
var debuggerTarget = new DebuggerTarget
{
Layout = callSight + "- ${logger}: ${message}"
};
var consoleTarget = new ColoredConsoleTarget
{
Layout = callSight + ": ${message}"
};
var fileTarget = new FileTarget
{
FileName = "${basedir}/test.log",
Layout = "${message}"
};
config.AddTarget("debugger", debuggerTarget);
config.AddTarget("console", consoleTarget);
//config.AddTarget("file", fileTarget);
// Step 3. Set target properties
// Step 4. Define rules
//LoggingRule fileRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
LoggingRule debugRule = new LoggingRule("*", LogLevel.Trace, debuggerTarget);
LoggingRule consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
//config.LoggingRules.Add(fileRule);
config.LoggingRules.Add(debugRule);
config.LoggingRules.Add(consoleRule);
// Step 5. Activate the configuration
LogManager.Configuration = config;
}
private static void ForceMigration(IRepository repository)
{
repository.GetPaged<Series>(0, 1);

@ -0,0 +1,114 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using Exceptioneer.WindowsFormsClient;
using NLog;
using NLog.Config;
using NLog.Targets;
namespace NzbDrone.Core
{
public static class Instrumentation
{
public static void Setup()
{
// Step 1. Create configuration object
var config = new LoggingConfiguration();
const string callSight = "${callsite:className=false:fileName=false:includeSourcePath=false:methodName=true}";
string layout = string.Concat("[${logger}](", callSight, "): ${message}");
// Step 2. Create targets and add them to the configuration
var debuggerTarget = new DebuggerTarget
{
Layout = layout
};
var consoleTarget = new ColoredConsoleTarget
{
Layout = layout
};
var fileTarget = new FileTarget
{
FileName = "${basedir}/test.log",
Layout = layout
};
config.AddTarget("debugger", debuggerTarget);
config.AddTarget("console", consoleTarget);
//config.AddTarget("file", fileTarget);
// Step 3. Set target properties
// Step 4. Define rules
//LoggingRule fileRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
var debugRule = new LoggingRule("*", LogLevel.Trace, debuggerTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
//config.LoggingRules.Add(fileRule);
config.LoggingRules.Add(debugRule);
config.LoggingRules.Add(consoleRule);
// Step 5. Activate the configuration
LogManager.Configuration = config;
}
public static void LogEpicException(Exception e)
{
try
{
LogManager.GetLogger("EPICFAIL").FatalException("Unhandled Exception", e);
}
catch (Exception totalFailException)
{
Console.WriteLine("TOTAL FAIL:{0}", totalFailException);
Console.WriteLine(e.ToString());
}
PublishExceptoion(e);
}
private static bool PublishExceptoion(Exception e)
{
//Don't publish exceptions when debugging the app.
if (Debugger.IsAttached)
return false;
return new Client
{
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265",
ApplicationName = "NZBDrone",
CurrentException = e
}.Submit();
}
public class NlogWriter : TextWriter
{
private static readonly Logger Logger = LogManager.GetLogger("DB");
public override void Write(char[] buffer, int index, int count)
{
Write(new string(buffer, index, count));
}
public override void Write(string value)
{
DbAction(value);
}
private static void DbAction(string value)
{
Logger.Trace(value);
}
public override Encoding Encoding
{
get { return Encoding.Default; }
}
}
}
}

@ -125,6 +125,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Exceptioneer.WindowsFormsClient, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL" />
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" />
<Reference Include="NLog.Extended, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
@ -150,6 +154,7 @@
<Compile Include="Entities\Notification\BasicNotification.cs" />
<Compile Include="Entities\Notification\NotificationStatus.cs" />
<Compile Include="Entities\Notification\NotificationType.cs" />
<Compile Include="Instrumentation.cs" />
<Compile Include="Providers\Fakes\FakeNotificationProvider.cs" />
<Compile Include="Providers\INotificationProvider.cs" />
<Compile Include="Providers\IMediaDiscoveryProvider.cs" />
@ -158,7 +163,6 @@
<Compile Include="Providers\XBMCMediaProvider.cs" />
<Compile Include="Entities\Notification\ProgressNotification.cs" />
<Compile Include="Providers\NotificationProvider.cs" />
<Compile Include="SonicTrace.cs" />
<Compile Include="Providers\ConfigProvider.cs" />
<Compile Include="Providers\EpisodeProvider.cs" />
<Compile Include="Providers\HttpProvider.cs" />
@ -211,6 +215,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Libraries\Castle.Core.dll" />
<Content Include="Libraries\Exceptioneer.WindowsFormsClient.dll" />
<Content Include="Libraries\log4net.dll" />
<Content Include="Libraries\log4net.xml" />
<Content Include="Libraries\Ninject.dll" />

@ -1,39 +0,0 @@
/*
*Source:http://stackoverflow.com/questions/1520945/nlog-to-output-db-out
*DamienG
*/
using System;
using System.IO;
using System.Text;
using NLog;
namespace NzbDrone.Core
{
class SonicTrace : TextWriter
{
private static readonly Logger Logger = LogManager.GetLogger("DB");
public override void Write(char[] buffer, int index, int count)
{
Write(new string(buffer, index, count));
}
public override void Write(string value)
{
DbAction(value);
}
private static void DbAction(string value)
{
Logger.Trace(value);
}
public override Encoding Encoding
{
get { return Encoding.Default; }
}
}
}

@ -1,10 +1,13 @@
using System.Web.Mvc;
using System;
using System.Diagnostics;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Ninject;
using Ninject.Web.Mvc;
using NLog;
using NzbDrone.Core;
namespace NzbDrone.Web
{
public class MvcApplication : NinjectHttpApplication
@ -21,12 +24,11 @@ namespace NzbDrone.Web
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Series", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected override void OnApplicationStarted()
{
CentralDispatch.ConfigureNlog();
Instrumentation.Setup();
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
base.OnApplicationStarted();
@ -35,9 +37,15 @@ namespace NzbDrone.Web
protected override IKernel CreateKernel()
{
return CentralDispatch.NinjectKernel;
}
// ReSharper disable InconsistentNaming
protected void Application_Error(object sender, EventArgs e)
{
Instrumentation.LogEpicException(Server.GetLastError());
}
}
}

@ -260,16 +260,7 @@
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>21704</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost/NzbDrone</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
<SaveServerSettingsInUserFile>True</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>

@ -11,15 +11,3 @@
<br />
<%:Model.Exception.ToString()%>
</asp:Content>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
try
{
LogManager.GetLogger("EPICFAIL").FatalException("Unhandled Exception", Model.Exception);
}
catch (Exception)
{
}
}
</script>

@ -21,13 +21,9 @@
<!--<add namespace="NzbDrone.Core.Repository"/>-->
</namespaces>
</pages>
<customErrors mode="RemoteOnly"/>
<customErrors mode="On"/>
</system.web>
<system.web.extensions />
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>

Binary file not shown.

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using NLog;
using NLog.Config;
using NLog.Targets;
namespace NzbDrone
{
class Config
{
private static string _projectRoot = string.Empty;
internal static string ProjectRoot
{
get
{
if (string.IsNullOrEmpty(_projectRoot))
{
var appDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
while (appDir.GetDirectories("iisexpress").Length == 0)
{
if (appDir.Parent == null) throw new ApplicationException("Can't fine IISExpress folder.");
appDir = appDir.Parent;
}
_projectRoot = appDir.FullName;
}
return _projectRoot;
}
}
internal static void ConfigureNlog()
{
var config = new LoggingConfiguration();
var debuggerTarget = new DebuggerTarget
{
Layout = "${logger}: ${message}"
};
var consoleTarget = new ColoredConsoleTarget
{
Layout = "${logger}: ${message}"
};
config.AddTarget("debugger", debuggerTarget);
config.AddTarget("console", consoleTarget);
//config.AddTarget("file", fileTarget);
// Step 3. Set target properties
// Step 4. Define rules
//LoggingRule fileRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
var debugRule = new LoggingRule("*", LogLevel.Trace, debuggerTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
//config.LoggingRules.Add(fileRule);
config.LoggingRules.Add(debugRule);
config.LoggingRules.Add(consoleRule);
// Step 5. Activate the configuration
LogManager.Configuration = config;
}
internal static int Port
{
get { return Convert.ToInt32(ConfigurationManager.AppSettings.Get("port")); }
}
}
}

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Web.Administration;
using NLog;
namespace NzbDrone
{
class IISController
{
public static Process IISProcess { get; private set; }
private static readonly Logger IISLogger = LogManager.GetLogger("IISExpress");
private static readonly Logger Logger = LogManager.GetLogger("IISController");
private static readonly string IISFolder = Path.Combine(Config.ProjectRoot, @"IISExpress\");
private static readonly string IISExe = Path.Combine(IISFolder, @"iisexpress.exe");
internal static string AppUrl
{
get { return string.Format("http://localhost:{0}/", Config.Port); }
}
internal static Process StartIIS()
{
Logger.Info("Preparing IISExpress Server...");
IISProcess = new Process();
IISProcess.StartInfo.FileName = IISExe;
IISProcess.StartInfo.Arguments = "/config:IISExpress\\Appserver\\applicationhost.config";
IISProcess.StartInfo.WorkingDirectory = Config.ProjectRoot;
IISProcess.StartInfo.UseShellExecute = false;
IISProcess.StartInfo.RedirectStandardOutput = true;
IISProcess.StartInfo.RedirectStandardError = true;
IISProcess.StartInfo.CreateNoWindow = true;
IISProcess.OutputDataReceived += ((s, e) => IISLogger.Trace(e.Data));
IISProcess.ErrorDataReceived += ((s, e) => IISLogger.Fatal(e.Data));
//Set Variables for the config file.
Environment.SetEnvironmentVariable("NZBDRONE_PATH", Config.ProjectRoot);
UpdateIISConfig();
Logger.Info("Starting process. [{0}]", IISProcess.StartInfo.FileName);
IISProcess.Start();
IISProcess.BeginErrorReadLine();
IISProcess.BeginOutputReadLine();
return IISProcess;
}
internal static void StopIIS()
{
KillProcess(IISProcess);
}
internal static void KillOrphaned()
{
Logger.Trace("================================================");
Logger.Info("Finding orphaned IIS Processes.");
foreach (var process in Process.GetProcessesByName("IISExpress"))
{
Logger.Trace("-------------------------");
string processPath = process.MainModule.FileName;
Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, processPath);
if (CleanPath(processPath) == CleanPath(IISExe))
{
Logger.Info("[{0}]Process is considered orphaned.", process.Id);
KillProcess(process);
}
else
{
Logger.Info("[{0}]Process has a different start-up path. skipping.", process.Id);
}
Logger.Trace("-------------------------");
}
Logger.Trace("================================================");
}
private static void KillProcess(Process process)
{
if (process == null) return;
Logger.Info("[{0}]Killing process", process.Id);
process.Kill();
Logger.Info("[{0}]Waiting for exit", process.Id);
process.WaitForExit();
Logger.Info("[{0}]Process terminated successfully", process.Id);
}
private static void UpdateIISConfig()
{
Logger.Info(@"Configuring server to: [http://localhost:{0}]", Config.Port);
var serverManager = new ServerManager(Path.Combine(IISFolder, @"AppServer\applicationhost.config"));
serverManager.Sites["NZBDrone"].Bindings[0].BindingInformation = string.Format("*:{0}:", Config.Port);
serverManager.CommitChanges();
}
private static string CleanPath(string path)
{
return path.ToLower().Replace("\\", "").Replace("//", "//");
}
}
}

@ -13,6 +13,21 @@
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<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|x86' ">
<PlatformTarget>x86</PlatformTarget>
@ -34,25 +49,72 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Exceptioneer.WindowsFormsClient, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\NLog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ProcessAttacher.cs" />
<Compile Include="Config.cs" />
<Compile Include="IISController.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Microsoft.Web.Administration.dll" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</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" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<!-- 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.
<Target Name="BeforeBuild">

@ -0,0 +1,152 @@
/* SOURCE: http://lazy.codeplex.com/
* File: http://lazy.codeplex.com/SourceControl/changeset/view/55373#307770
* Author: pablito900
* Licence: GNU General Public License version 2 (GPLv2)
*/
#if DEBUG
using System;
using System.Collections.Generic;
using EnvDTE80;
namespace NzbDrone
{
public class ProcessAttacher
{
private enum AttachType
{
Managed,
Native,
ManagedAndNative
}
private enum AttachResult
{
Attached,
NotRunning,
BeingDebugged
}
public static void Attach()
{
// Get an instance of the currently running Visual Studio IDE.
DTE2 dte2;
dte2 = (DTE2)System.Runtime.InteropServices.Marshal.
GetActiveObject("VisualStudio.DTE.10.0");
var pa = new ProcessAttacher(dte2, "iisexpress", 20);
pa.OptimisticAttachManaged();
}
#region private
private readonly Dictionary<AttachType, string> _attachTypesMap;
private readonly DTE2 _dte;
private readonly string _processName;
private readonly int _waitTimeout;
#endregion
#region ctor
private ProcessAttacher(DTE2 dte, string processName, int waitTimeout)
{
_processName = processName;
_waitTimeout = waitTimeout;
_dte = dte;
_attachTypesMap = new Dictionary<AttachType, string> {
{AttachType.Managed, "Managed"}
};
}
#endregion
#region private methods
private AttachResult Attach(AttachType attachType)
{
string engine = _attachTypesMap[attachType];
if (IsBeingDebugged())
{
return AttachResult.BeingDebugged;
}
var dbg = _dte.Debugger as Debugger2;
var trans = dbg.Transports.Item("Default");
var eng = trans.Engines.Item(engine);
EnvDTE80.Process2 proc = null;
try
{
proc = dbg.GetProcesses(trans, "").Item(_processName) as EnvDTE80.Process2;
}
catch (Exception ex)
{
if (ex.Message.Contains("Invalid index."))
{
return AttachResult.NotRunning;
}
}
proc.Attach2(eng);
return AttachResult.Attached;
}
private AttachResult PessimisticAttach(AttachType attachType)
{
AttachResult res = Attach(attachType);
DateTime timeout = DateTime.Now.AddSeconds(_waitTimeout);
while (res == AttachResult.NotRunning && timeout > DateTime.Now)
{
res = Attach(attachType);
System.Threading.Thread.Sleep(100);
}
return res;
}
private bool IsBeingDebugged()
{
if (_dte.Debugger.DebuggedProcesses != null)
{
foreach (EnvDTE.Process process in _dte.Debugger.DebuggedProcesses)
{
if (process.Name.IndexOf(_processName) != -1)
{
return true;
}
}
}
return false;
}
#endregion
#region public methods
public void OptimisticAttachManaged()
{
Attach(AttachType.Managed);
}
public void PessimisticAttachManaged()
{
PessimisticAttach(AttachType.Managed);
}
#endregion
}
#endif
}

@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Exceptioneer.WindowsFormsClient;
using NLog;
using NLog.Config;
using NLog.Targets;
@ -12,166 +13,67 @@ namespace NzbDrone
{
private static readonly Logger Logger = LogManager.GetLogger("Application");
private static readonly Logger IISLogger = LogManager.GetLogger("IISExpress");
private static Process IISProcess;
static void Main()
{
try
{
AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e));
var projectRoot = GetProjectRoot();
ConfigureNlog();
Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", projectRoot);
var iisPath = Path.Combine(projectRoot, @"IISExpress\iisexpress.exe");
Logger.Info("IISExpress Path:'{0}'", iisPath);
KillOrphane(iisPath);
Logger.Info("Preparing IISExpress Server...");
IISProcess = new Process();
IISProcess.StartInfo.FileName = iisPath;
IISProcess.StartInfo.Arguments = "/config:IISExpress\\Appserver\\applicationhost.config";
IISProcess.StartInfo.WorkingDirectory = projectRoot;
AppDomain.CurrentDomain.ProcessExit += ProgramExited;
AppDomain.CurrentDomain.DomainUnload += ProgramExited;
System.Diagnostics.Process.GetCurrentProcess().Exited += ProgramExited;
IISProcess.StartInfo.UseShellExecute = false;
IISProcess.StartInfo.RedirectStandardOutput = true;
IISProcess.StartInfo.RedirectStandardError = true;
IISProcess.StartInfo.CreateNoWindow = true;
Config.ConfigureNlog();
IISProcess.OutputDataReceived += ((s, e) => IISLogger.Trace(e.Data));
IISProcess.ErrorDataReceived += ((s, e) => IISLogger.Fatal(e.Data));
Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", Config.ProjectRoot);
//Set Variables for the config file.
Environment.SetEnvironmentVariable("NZBDRONE_PATH", projectRoot);
IISController.KillOrphaned();
IISController.StartIIS();
Logger.Info("Starting process");
IISProcess.Start();
System.Diagnostics.Process.Start(IISController.AppUrl);
//Event handlers, try to terminate iis express before exiting application.
AppDomain.CurrentDomain.ProcessExit += ProgramExited;
AppDomain.CurrentDomain.DomainUnload += ProgramExited;
Process.GetCurrentProcess().Exited += ProgramExited;
#if DEBUG
//Manually Attach debugger to IISExpress
if (Debugger.IsAttached)
{
ProcessAttacher.Attach();
}
#endif
IISProcess.BeginErrorReadLine();
IISProcess.BeginOutputReadLine();
IISProcess.WaitForExit();
Logger.Info("Main IISExpress instance was terminated. ExitCode:{0}", IISProcess.ExitCode);
}
catch (Exception e)
{
AppDomainException(e);
}
Console.Write("Press Enter To Exit...");
Console.Write("Press Enter At Any Time To Exit...");
Console.ReadLine();
IISController.StopIIS();
}
private static string GetProjectRoot()
{
var appDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
while (appDir.GetDirectories("iisexpress").Length == 0)
{
if (appDir.Parent == null) throw new ApplicationException("Can't fine IISExpress folder.");
appDir = appDir.Parent;
}
return appDir.FullName;
}
private static void AppDomainException(object excepion)
{
Console.WriteLine("EPIC FAIL: {0}", excepion);
Logger.Fatal("EPIC FAIL: {0}", excepion);
KillProcess(IISProcess);
}
static void ProgramExited(object sender, EventArgs e)
{
KillProcess(IISProcess);
}
private static void KillOrphane(string path)
{
Logger.Trace("================================================");
Logger.Info("Finding orphaned IIS Processes.");
foreach (var process in Process.GetProcessesByName("IISExpress"))
new Client
{
Logger.Trace("-------------------------");
string processPath = process.MainModule.FileName;
Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, processPath);
if (CleanPath(processPath) == CleanPath(path))
{
Logger.Info("[{0}]Process is considered orphaned.", process.Id);
KillProcess(process);
}
else
{
Logger.Info("[{0}]Process has a different start-up path. skipping.", process.Id);
}
Logger.Trace("-------------------------");
}
Logger.Trace("================================================");
}
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265",
ApplicationName = "NZBDrone",
CurrentException = excepion as Exception
}.Submit();
private static void KillProcess(Process process)
{
if (process != null)
{
Logger.Info("[{0}]Killing process", process.Id);
process.Kill();
Logger.Info("[{0}]Waiting for exit", process.Id);
process.WaitForExit();
Logger.Info("[{0}]Process terminated successfully", process.Id);
}
IISController.StopIIS();
}
private static string CleanPath(string path)
static void ProgramExited(object sender, EventArgs e)
{
return path.ToLower().Replace("\\", "").Replace("//", "//");
IISController.StopIIS();
}
private static void ConfigureNlog()
{
var config = new LoggingConfiguration();
var debuggerTarget = new DebuggerTarget
{
Layout = "${logger}: ${message}"
};
var consoleTarget = new ColoredConsoleTarget
{
Layout = "${logger}: ${message}"
};
config.AddTarget("debugger", debuggerTarget);
config.AddTarget("console", consoleTarget);
//config.AddTarget("file", fileTarget);
// Step 3. Set target properties
// Step 4. Define rules
//LoggingRule fileRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
var debugRule = new LoggingRule("*", LogLevel.Trace, debuggerTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
//config.LoggingRules.Add(fileRule);
config.LoggingRules.Add(debugRule);
config.LoggingRules.Add(consoleRule);
// Step 5. Activate the configuration
LogManager.Configuration = config;
}
}
}

@ -1,7 +1,9 @@
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
<supportedRuntime version="v4.0" />
</startup>
</configuration>
<appSettings>
<add key="port" value="8981" />
</appSettings>
</configuration>
Loading…
Cancel
Save