Remotely/Shared/Utilities/Logger.cs
Jared Goodwin 3ef4cdf81a
Extract remote control functionality into separate library. (#539)
* Convert server to new single-file startup model.

* Add remote control implementations.

* Implement IViewerAuthorizer.

* Update hub endpoints.

* Implement HubEventHandler.

* Implement ViewerHubDataProvider.

* Implement page data provider.

* Implement RCL and refactor.

* Update submodule.

* Replace submodule with NuGet.

* Update copy URL.

* Update NuGet.

* Remove deprecated WebRTC.

* Remove deprecated WebRTC.

* Update Immense.RemoteControl

* Building out desktop projects.

* Bring more services into submodule.

* Update submodule.

* Update submodule.

* Refactoring for module.

* Update submodule.

* Update submodule

* Got Windows desktop app running.

* Refactor for submodule changes.

* FIx unattended session start.

* Switch desktop app out of console mode.

* Fix tests.

* Update publishing.

* Remove ClickOnce middleware.

* Remove ClickOnce remnants.

* Update submodule

* Add some logging.

* Update Linux path.

* Update submodule.

* Add cleanup service for unattended sessions that failed to start.

* Update submodule.

* Fix chat.

* Add ValidateExecutableReferencesMatchSelfContained property.

* Add other submodule projects.  Align checkbox.

* Update submodule.  Reduce deserialization in the browser, resulting in faster renders.

* Update submodule.

* Update submodule.

* Update submodule.

* Update submodule.

* Add orgId back for branding.

* Get branding loading in desktop apps.

* Update submodule.

* Create log dir.

* Refactor version check on config page.

* Update submodule.

* Update submodule.

* Change submodule URL.

* Correct namespace.

* Update submodule.

* Checkout submodules recursively.
2022-12-23 06:39:12 -08:00

151 lines
4.5 KiB
C#

using Remotely.Shared.Enums;
using Remotely.Shared.Utilities;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace Remotely.Shared.Utilities
{
// TODO: Replace this with ILogger<T>.
public static class Logger
{
private static string LogDir => Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "Remotely", "Logs")).FullName;
private static string LogPath => Path.Combine(LogDir, $"LogFile_{DateTime.Now:yyyy-MM-dd}.log");
private static SemaphoreSlim WriteLock { get; } = new(1, 1);
public static void Debug(string message, [CallerMemberName] string callerName = "")
{
try
{
WriteLock.Wait();
if (EnvironmentHelper.IsDebug)
{
CheckLogFileExists();
File.AppendAllText(LogPath, $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff}\t[Debug]\t[{callerName}]\t{message}{Environment.NewLine}");
}
System.Diagnostics.Debug.WriteLine(message);
}
catch { }
finally
{
WriteLock.Release();
}
}
public static void DeleteLogs()
{
try
{
WriteLock.Wait();
if (File.Exists(LogPath))
{
File.Delete(LogPath);
}
}
catch { }
finally
{
WriteLock.Release();
}
}
public static async Task<byte[]> ReadAllLogs()
{
try
{
WriteLock.Wait();
CheckLogFileExists();
return await File.ReadAllBytesAsync(LogPath);
}
catch (Exception ex)
{
Write(ex);
return Array.Empty<byte>();
}
finally
{
WriteLock.Release();
}
}
public static void Write(string message, EventType eventType = EventType.Info, [CallerMemberName] string callerName = "")
{
try
{
WriteLock.Wait();
CheckLogFileExists();
File.AppendAllText(LogPath, $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff}\t[{eventType}]\t[{callerName}]\t{message}{Environment.NewLine}");
Console.WriteLine(message);
}
catch { }
finally
{
WriteLock.Release();
}
}
public static void Write(Exception ex, EventType eventType = EventType.Error, [CallerMemberName] string callerName = "")
{
try
{
WriteLock.Wait();
CheckLogFileExists();
var exception = ex;
while (exception != null)
{
File.AppendAllText(LogPath, $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff}\t[{eventType}]\t[{callerName}]\t{exception?.Message}\t{exception?.StackTrace}\t{exception?.Source}{Environment.NewLine}");
Console.WriteLine(exception.Message);
exception = exception.InnerException;
}
}
catch { }
finally
{
WriteLock.Release();
}
}
public static void Write(Exception ex, string message, EventType eventType = EventType.Error, [CallerMemberName] string callerName = "")
{
Write(message, eventType, callerName);
Write(ex, eventType, callerName);
}
private static void CheckLogFileExists()
{
if (!File.Exists(LogPath))
{
File.Create(LogPath).Close();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("sudo", $"chmod 777 {LogPath}").WaitForExit();
}
}
if (File.Exists(LogPath))
{
var fi = new FileInfo(LogPath);
while (fi.Length > 1000000)
{
var content = File.ReadAllLines(LogPath);
File.WriteAllLines(LogPath, content.Skip(10));
fi = new FileInfo(LogPath);
}
}
}
}
}