Compare commits
No commits in common. "33ebee08dbdf86ea3e2d73a20f3cfb7334d8bfe9" and "672046d02e117f9b41b70fc625e1af0ab73ef678" have entirely different histories.
33ebee08db
...
672046d02e
@ -1,12 +0,0 @@
|
|||||||
namespace Marco.Pms.Model.Logs
|
|
||||||
{
|
|
||||||
public class LogStructure
|
|
||||||
{
|
|
||||||
public string LogLevel { get; set; } = "Info";
|
|
||||||
public string Message { get; set; } = string.Empty;
|
|
||||||
public DateTime TimeStamp { get; set; }
|
|
||||||
public string? IpAddress { get; set; }
|
|
||||||
public string? UserAgent { get; set; }
|
|
||||||
public string? Details { get; set; } // json serialized string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
using Marco.Pms.Model.Logs;
|
|
||||||
using Marco.Pms.Model.Utilities;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Serilog.Context;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace Marco.Pms.Services.Controllers
|
|
||||||
{
|
|
||||||
[Authorize]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
public class LogController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ILogger<LogController> _logger;
|
|
||||||
public LogController(ILogger<LogController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
/// <summary>
|
|
||||||
/// Receives a batch of log entries from mobile applications and processes them.
|
|
||||||
/// Logs are enriched with context properties like UserAgent, Timestamp, and IpAddress.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="logs">A list of LogStructure objects containing log details.</param>
|
|
||||||
/// <returns>An <see cref="IActionResult"/> indicating the success of the operation.</returns>
|
|
||||||
public IActionResult MobileLogging([FromBody] List<LogStructure> logs)
|
|
||||||
{
|
|
||||||
// Check if logs are provided to avoid processing empty requests
|
|
||||||
if (logs == null || !logs.Any())
|
|
||||||
{
|
|
||||||
_logger.LogWarning("MobileLogging endpoint received an empty or null log list.");
|
|
||||||
return BadRequest("No log entries provided.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through each log entry received from the client
|
|
||||||
foreach (var log in logs)
|
|
||||||
{
|
|
||||||
object? detailsObject = null;
|
|
||||||
|
|
||||||
// Attempt to deserialize the 'Details' string into a dynamic object
|
|
||||||
// This allows structured logging of the details payload.
|
|
||||||
if (!string.IsNullOrWhiteSpace(log.Details))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Use JsonDocument for potentially more efficient parsing if you just need the raw JSON or a dynamic object
|
|
||||||
// For simply logging it as a structured property, object works.
|
|
||||||
detailsObject = JsonSerializer.Deserialize<Dictionary<string, string>>(log.Details);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (JsonException ex)
|
|
||||||
{
|
|
||||||
// Log a warning if deserialization fails, but continue processing other logs
|
|
||||||
_logger.LogWarning("Failed to deserialize 'Details' for a log entry. Raw details: '{RawDetails}'. Error: {ErrorMessage}", log.Details, ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push common properties to the Serilog LogContext for the current log operation.
|
|
||||||
// These properties will be attached to the log event itself.
|
|
||||||
using (LogContext.PushProperty("UserAgent", log.UserAgent))
|
|
||||||
using (LogContext.PushProperty("Timestamp", log.TimeStamp))
|
|
||||||
using (LogContext.PushProperty("IpAddress", log.IpAddress))
|
|
||||||
using (LogContext.PushProperty("LogOrigin", "Mobile Application"))
|
|
||||||
{
|
|
||||||
// If details were successfully parsed, push them as a structured property.
|
|
||||||
if (detailsObject != null)
|
|
||||||
{
|
|
||||||
using (LogContext.PushProperty("Details", detailsObject, true)) // 'true' for destructuring
|
|
||||||
{
|
|
||||||
LogByLevel(log.LogLevel, log.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If details were null or failed to parse, log without the details property
|
|
||||||
LogByLevel(log.LogLevel, log.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return 200 OK indicating successful receipt of logs.
|
|
||||||
// As logging is typically a "fire and forget" operation from the client's perspective,
|
|
||||||
// we don't need to await individual log writes here.
|
|
||||||
// The logger provider handles the actual writing asynchronously in the background.
|
|
||||||
_logger.LogInformation("Successfully processed {LogCount} mobile log entries.", logs.Count);
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Logs received successfully.", 200));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Logs a message at the specified log level using the injected ILogger.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="logLevel">The string representation of the log level (e.g., "info", "warning").</param>
|
|
||||||
/// <param name="message">The log message.</param>
|
|
||||||
private void LogByLevel(string? logLevel, string? message)
|
|
||||||
{
|
|
||||||
// Default message if null or empty
|
|
||||||
message = string.IsNullOrWhiteSpace(message) ? "No message provided." : message;
|
|
||||||
|
|
||||||
// Use a switch expression or simple if/else for clarity based on log level
|
|
||||||
switch (logLevel?.ToLowerInvariant()) // Use ToLowerInvariant for case-insensitive comparison
|
|
||||||
{
|
|
||||||
case "debug":
|
|
||||||
_logger.LogDebug(message);
|
|
||||||
break;
|
|
||||||
case "info":
|
|
||||||
case "information": // Common alias for info
|
|
||||||
_logger.LogInformation(message);
|
|
||||||
break;
|
|
||||||
case "warn":
|
|
||||||
case "warning":
|
|
||||||
_logger.LogWarning(message);
|
|
||||||
break;
|
|
||||||
case "error":
|
|
||||||
_logger.LogError(message);
|
|
||||||
break;
|
|
||||||
case "critical":
|
|
||||||
_logger.LogCritical(message);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Log unknown levels as information to ensure they are captured
|
|
||||||
_logger.LogInformation("[Unknown Level] {Message}", message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using MarcoBMS.Services.Service;
|
using System.Diagnostics;
|
||||||
|
using MarcoBMS.Services.Service;
|
||||||
using Serilog.Context;
|
using Serilog.Context;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace MarcoBMS.Services.Middleware
|
namespace MarcoBMS.Services.Middleware
|
||||||
{
|
{
|
||||||
@ -34,7 +34,6 @@ namespace MarcoBMS.Services.Middleware
|
|||||||
using (LogContext.PushProperty("IpAddress", context.Connection.RemoteIpAddress?.ToString()))
|
using (LogContext.PushProperty("IpAddress", context.Connection.RemoteIpAddress?.ToString()))
|
||||||
using (LogContext.PushProperty("RequestPath", request.Path))
|
using (LogContext.PushProperty("RequestPath", request.Path))
|
||||||
using (LogContext.PushProperty("Origin", origin))
|
using (LogContext.PushProperty("Origin", origin))
|
||||||
using (LogContext.PushProperty("LogOrigin", "ASP .NET Api"))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
void LogDebug(string? message, params object[]? args);
|
void LogDebug(string? message, params object[]? args);
|
||||||
void LogWarning(string? message, params object[]? args);
|
void LogWarning(string? message, params object[]? args);
|
||||||
void LogError(Exception? ex, string? message, params object[]? args);
|
void LogError(Exception? ex, string? message, params object[]? args);
|
||||||
void LogCritical(string? message, params object[]? args);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,19 +61,6 @@ namespace MarcoBMS.Services.Service
|
|||||||
_logger.LogWarning(message);
|
_logger.LogWarning(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogCritical(string? message, params object[]? args)
|
|
||||||
{
|
|
||||||
using (LogContext.PushProperty("LogLevel", "Critical"))
|
|
||||||
if (args != null)
|
|
||||||
{
|
|
||||||
_logger.LogCritical(message, args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogCritical(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user