Updated logging and instrumentation
This commit is contained in:
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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -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("//", "//");
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -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;
|
||||
|
||||
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", projectRoot);
|
||||
|
||||
Logger.Info("Starting process");
|
||||
IISProcess.Start();
|
||||
|
||||
//Event handlers, try to terminate iis express before exiting application.
|
||||
AppDomain.CurrentDomain.ProcessExit += ProgramExited;
|
||||
AppDomain.CurrentDomain.DomainUnload += ProgramExited;
|
||||
Process.GetCurrentProcess().Exited += ProgramExited;
|
||||
System.Diagnostics.Process.GetCurrentProcess().Exited += ProgramExited;
|
||||
|
||||
Config.ConfigureNlog();
|
||||
|
||||
Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", Config.ProjectRoot);
|
||||
|
||||
IISController.KillOrphaned();
|
||||
IISController.StartIIS();
|
||||
|
||||
System.Diagnostics.Process.Start(IISController.AppUrl);
|
||||
|
||||
#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);
|
||||
|
||||
new Client
|
||||
{
|
||||
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265",
|
||||
ApplicationName = "NZBDrone",
|
||||
CurrentException = excepion as Exception
|
||||
}.Submit();
|
||||
|
||||
IISController.StopIIS();
|
||||
}
|
||||
|
||||
static void ProgramExited(object sender, EventArgs e)
|
||||
{
|
||||
KillProcess(IISProcess);
|
||||
IISController.StopIIS();
|
||||
}
|
||||
|
||||
private static void KillOrphane(string path)
|
||||
{
|
||||
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(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("================================================");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private static string CleanPath(string path)
|
||||
{
|
||||
return path.ToLower().Replace("\\", "").Replace("//", "//");
|
||||
}
|
||||
|
||||
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…
Reference in New Issue