Skip to content

Commit

Permalink
Logging utility added, more unit test, documentation in code.
Browse files Browse the repository at this point in the history
  • Loading branch information
mathis1337 committed Aug 17, 2023
1 parent 0a85da4 commit c0adfd7
Show file tree
Hide file tree
Showing 15 changed files with 621 additions and 4 deletions.
5 changes: 3 additions & 2 deletions ArcherCore/APIs/APIUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ namespace ArcherCore.APIs
public static class APIUtilities
{
//"https://api.github.com/repos/ReserveBlockIO/ReserveBlock-Core/releases/latest"
public static async Task<Release?> GetLatestGithubRelease(string url)
public static async Task<Release?> GetLatestGithubRelease(string url, string productName, string productVersion)
{
try
{
HttpClient client = new HttpClient();
var productValue = new ProductInfoHeaderValue("RBX-Version-Check", "1.0");
//var productValue = new ProductInfoHeaderValue("RBX-Version-Check", "1.0");
var productValue = new ProductInfoHeaderValue(productName, productVersion);

client.DefaultRequestHeaders.UserAgent.Add(productValue);
var httpResponse = await client.GetAsync(url);
Expand Down
56 changes: 56 additions & 0 deletions ArcherCore/Archer.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using ArcherCore.Email;
using ArcherCore.Http;
using ArcherCore.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net.Mail;
using System.Runtime.InteropServices;

namespace ArcherCore
{
Expand Down Expand Up @@ -34,6 +38,58 @@ public static async Task SetupHttpClientFactory(bool enableLogging = false, stri
HttpVariables.HttpClientFactory = httpClientBuilder.Services.GetRequiredService<HttpService>().HttpClientFactory();
}

public static async Task SetupLogging(string? logPath = null, bool? useDb = false)
{
var databaseLocation = "Logs";
var mainFolderPath = "ArcherCore";

if (logPath == null)
{
string path = "";
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
string homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
path = homeDirectory + Path.DirectorySeparatorChar + mainFolderPath.ToLower() + Path.DirectorySeparatorChar + databaseLocation + Path.DirectorySeparatorChar;
}
else
{
if (Debugger.IsAttached)
{
path = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "Logs" + Path.DirectorySeparatorChar + databaseLocation + Path.DirectorySeparatorChar;
}
else
{
path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + Path.DirectorySeparatorChar + mainFolderPath + Path.DirectorySeparatorChar + databaseLocation + Path.DirectorySeparatorChar;
}
}

if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}

LoggingVariables.LoggingPath = path;
LoggingVariables.UseDb = useDb.Value;
}
else
{
if (!Directory.Exists(logPath))
{
Directory.CreateDirectory(logPath);
}

LoggingVariables.LoggingPath = logPath;
LoggingVariables.UseDb = useDb.Value;
}

if(useDb.Value)
{
await LoggingService.InitializeDb();
}

_ = LoggingService.LogLoop();
}

public static async Task ForceUSCulture()
{
var culture = CultureInfo.GetCultureInfo("en-US");
Expand Down
2 changes: 0 additions & 2 deletions ArcherCore/ArcherCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
</PropertyGroup>

<ItemGroup>
<Folder Include="Logging\" />
<Folder Include="Database\" />
<Folder Include="BackgroundTask\" />
<Folder Include="Memory\" />
<Folder Include="Compression\" />
<Folder Include="Backup\" />
<Folder Include="Port\" />
<Folder Include="WebRequest\" />
</ItemGroup>

<ItemGroup>
Expand Down
31 changes: 31 additions & 0 deletions ArcherCore/Logging/LoggingModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using LiteDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArcherCore.Logging
{
/// <summary>
/// Model for creating a log variable.
/// </summary>
public class LoggingModel
{
/// <value>Property <c>Id</c> represents key for record</value>
[BsonId]
public long Id { get; set; }

/// <value>Property <c>Message</c> represents the content for the log.</value>
public string Message { get; set; }

/// <value>Property <c>LogType</c> represents the type of logging (Info, Error, Warning, etc.)</value>
public string LogType { get; set; }

/// <value>Property <c>Location</c> represents the location of where the error occurred.</value>
public string Location { get; set; }

/// <value>Property <c>Time</c> represents the time in which the error occurred.</value>
public DateTime Time { get; set; }
}
}
69 changes: 69 additions & 0 deletions ArcherCore/Logging/LoggingService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using LiteDB;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArcherCore.Logging
{
public static class LoggingService
{
/// <summary>
/// Starts the logging loop for logging services.
/// </summary>
public static async Task LogLoop()
{
while (true)
{
while (LoggingVariables.LogQueue.Count > 0)
{
if (LoggingVariables.LogQueue.TryDequeue(out var content))
{
if(!LoggingVariables.UseDb)
{
var text = "[" + content.Time + "]" + "[" + content.LogType + "]" + " : " + "[" + content.Location + "]" + " : " + content.Message;
await File.AppendAllTextAsync(LoggingVariables.LoggingPath + "Log.txt", Environment.NewLine + text);
}
else
{
var logsDb = LoggingVariables.LogDb.GetCollection<LoggingModel>(LoggingVariables.ARCHER_LOG);
if(logsDb != null)
{
var log = new LoggingModel {
Location = content.Location,
LogType = content.LogType,
Message = content.Message,
Time = content.Time
};

logsDb.Insert(log);
}
}
}
}

await Task.Delay(20);
}
}

/// <summary>
/// Starts the DB Service for logging service.
/// </summary>
public static async Task InitializeDb()
{
var mapper = new BsonMapper();
mapper.RegisterType<DateTime>(
value => value.ToString("o", CultureInfo.InvariantCulture),
bson => DateTime.ParseExact(bson, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind));
mapper.RegisterType<DateTimeOffset>(
value => value.ToString("o", CultureInfo.InvariantCulture),
bson => DateTimeOffset.ParseExact(bson, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind));

string path = LoggingVariables.LoggingPath;
LoggingVariables.LogDb = new LiteDatabase(new ConnectionString { Filename = path + LoggingVariables.ARCHER_DB_NAME, Connection = ConnectionType.Direct, ReadOnly = false }, mapper);
}
}
}
69 changes: 69 additions & 0 deletions ArcherCore/Logging/LoggingUtilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using LiteDB;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArcherCore.Logging
{
public static class LoggingUtilities
{
/// <summary>
/// Add a row to the log queue
/// </summary>
/// <param name="message">input string</param>
/// <param name="logType">input string</param>
/// <param name="location">input string</param>
/// <param name="time">input DateTime</param>
public static async Task Log(string message, string logType, string location, DateTime time)
{
LoggingVariables.LogQueue.Enqueue((message, logType, location, DateTime.Now));
}

/// <summary>
/// Gets the most recent 100 records by default for a log
/// </summary>
/// <param name="logCount">input int</param>
/// <returns>
/// Returns a List<LoggingModel>?
/// </returns>
public static async Task<List<LoggingModel>?> GetLog(int logCount = 100)
{
var logsDb = LoggingVariables.LogDb.GetCollection<LoggingModel>(LoggingVariables.ARCHER_LOG);
var recentLogs = logsDb.Find(Query.All(Query.Descending)).Take(logCount).ToList();

if(recentLogs.Count > 0 )
{
return recentLogs;
}
else
{
return null;
}
}

/// <summary>
/// Gets the most recent 100 records by default for a log and serializes it.
/// </summary>
/// <param name="logCount">input int</param>
/// <returns>
/// Returns a JSON string?
/// </returns>
public static async Task<string?> GetLogJson(int logCount = 100)
{
var logsDb = LoggingVariables.LogDb.GetCollection<LoggingModel>(LoggingVariables.ARCHER_LOG);
var recentLogs = logsDb.Find(Query.All(Query.Descending)).Take(logCount).ToList();

if (recentLogs.Count > 0)
{
return JsonConvert.SerializeObject(recentLogs);
}
else
{
return null;
}
}
}
}
20 changes: 20 additions & 0 deletions ArcherCore/Logging/LoggingVariables.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using LiteDB;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArcherCore.Logging
{
public static class LoggingVariables
{
public static string LoggingPath = "";
public static bool UseDb = false;
public static ConcurrentQueue<(string Message, string LogType, string Location, DateTime Time)> LogQueue = new ConcurrentQueue<(string, string, string, DateTime)>();
public static LiteDatabase LogDb { get; set; }
public const string ARCHER_DB_NAME = @"log.db";
public const string ARCHER_LOG = "archer_log";
}
}
15 changes: 15 additions & 0 deletions ArcherCore/Numbers/NumberUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ namespace ArcherCore.Numbers
{
public static class NumberUtilities
{
/// <summary>
/// Finds the closest number to the given inputNumber
/// </summary>
/// <param name="inputNumber">input long</param>
/// <param name="numbers">input long[]?</param>
/// <returns>
/// Returns a long that is closest to input.
/// </returns>
public static long FindClosestNumber(long inputNumber, long[]? numbers = null)
{
numbers = numbers == null ? new long[] { 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 128, 256, 512, 1024, 2048, 5096 } : numbers;
Expand All @@ -29,6 +37,13 @@ public static long FindClosestNumber(long inputNumber, long[]? numbers = null)
return closestNumber;
}

/// <summary>
/// Gets amount of decimal places from the given number
/// </summary>
/// <param name="number">input decimal</param>
/// <returns>
/// Returns an int count of number of decimal places.
/// </returns>
public static int GetNumberOfDecimalPlaces(decimal number)
{
var decimalsUsed = BitConverter.GetBytes(decimal.GetBits(number)[3])[2];
Expand Down
6 changes: 6 additions & 0 deletions ArcherCore/Platform/PlatformUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ namespace ArcherCore.Platform
{
public static class PlatformUtilities
{
/// <summary>
/// This method will return what the detected platform is
/// </summary>
/// <returns>
/// Returns a string of 'win', 'mac', or 'linux'
/// </returns>
public static string GetPlatform()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
Expand Down
17 changes: 17 additions & 0 deletions ArcherCore/Randomization/RandomUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ namespace ArcherCore.Randomization
{
public static class RandomUtilities
{
/// <summary>
/// This method gets a random string based on length of numOfChars
/// </summary>
/// <param name="numOfChars">input int</param>
/// <param name="onlyLetters">input bool</param>
/// <param name="addTimestamp">input bool</param>
/// <returns>
/// Returns a random string
/// </returns>
public static string GetRandomString(int numOfChars, bool onlyLetters = false, bool addTimestamp = false)
{
var chars = !onlyLetters ? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Expand All @@ -25,6 +34,14 @@ public static string GetRandomString(int numOfChars, bool onlyLetters = false, b
return finalString;
}

/// <summary>
/// This method gets a random number between min and max
/// </summary>
/// <param name="min">input int</param>
/// <param name="max">input int</param>
/// <returns>
/// Returns a int between min and max
/// </returns>
public static int GetRandomNumber(int? min = 0, int? max = int.MaxValue)
{
int randomNumber = 0;
Expand Down
Loading

0 comments on commit c0adfd7

Please sign in to comment.