Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ttpullima/RomsoftBackEnd2021_v2/llms.txt
Use this file to discover all available pages before exploring further.
The Gestión Clínica API employs two complementary logging mechanisms that serve distinct purposes. The first is log4net, which captures unexpected exceptions and infrastructure errors to a rolling text file on the server filesystem. The second is a database audit log powered by LogBL, which records every intentional user action — patient registration, insurance plan update, login — as a structured row in the database, giving clinic administrators a permanent, queryable trail of who did what and when.
Mechanism 1 — log4net Exception Logging
Configuration in Web.config
log4net is configured entirely within Web.config using a dedicated <log4net> section. The section handler is declared in <configSections> at the top of the file:
<configSections>
<section
name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
The log4net section itself defines two appenders and a root logger:
<log4net>
<!-- Writes to the Visual Studio Output / Debug console -->
<appender name="DebugAppender" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger - %message%newline" />
</layout>
</appender>
<!-- Writes to Log/Log.txt with size-based rolling -->
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Log/Log.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger - %message%newline" />
</layout>
</appender>
<!-- Root logger: capture everything (ALL level), send to both appenders -->
<root>
<level value="All" />
<appender-ref ref="DebugAppender" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
Rolling File Appender Settings
| Setting | Value | Meaning |
|---|
file | Log/Log.txt | Path relative to the IIS application root |
appendToFile | true | New entries are appended, not overwriting the file |
rollingStyle | Size | Roll files when size limit is reached |
maxSizeRollBackups | 10 | Keep up to 10 backup files (Log.txt.1 … Log.txt.10) |
maximumFileSize | 1MB | Roll to a new backup when current file exceeds 1 MB |
staticLogFileName | true | Active log always named Log.txt; backups get numeric suffixes |
Pattern Layout
Each log entry uses the pattern %date %-5level %logger - %message%newline, which produces lines such as:
2024-03-15 09:42:17,334 ERROR - Mensaje: Object reference not set Trace: at Romsoft…
| Token | Output |
|---|
%date | Full timestamp including milliseconds |
%-5level | Log level left-padded to 5 characters (ERROR, WARN , INFO ) |
%logger | Logger name (empty string for the root logger) |
%message | The formatted message |
%newline | Platform-appropriate line terminator |
Bootstrapping log4net
log4net is initialized once in Global.asax.cs during Application_Start:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
log4net.Config.XmlConfigurator.Configure(); // reads <log4net> from Web.config
AutoMapperConfiguration.Configure();
}
Using the Logger in Controllers
BaseController exposes a shared root logger as a protected static field:
public class BaseController : ApiController
{
protected static readonly ILog Logger =
LogManager.GetLogger(string.Empty); // binds to root logger
protected void LogError(Exception exception)
{
Logger.Error(string.Format(
"Mensaje: {0} Trace: {1}",
exception.Message,
exception.StackTrace));
}
protected void LogError(string mensaje)
{
Logger.Error(mensaje);
}
}
Every controller action wraps its body in a try/catch and calls LogError(ex) in the catch block. This ensures that no exception is silently swallowed — it always lands in Log/Log.txt alongside a JsonResponse with Success=false.
Mechanism 2 — Database Audit Log
The Log Entity
The Log class in Romsoft.GESTIONCLINICA.Entidades defines the schema of the audit record:
public class Log
{
public int Id { get; set; }
public string DireccionIP { get; set; } // Client IP address
public string Usuario { get; set; } // Username performing the action
public string Mensaje { get; set; } // Outcome message
public string Controlador { get; set; } // Controller name (e.g. "Usuario")
public string Accion { get; set; } // Action name (e.g. "Add", "Update")
public DateTime FechaRegistro { get; set; } // Timestamp (set by DB default)
public string Objeto { get; set; } // JSON-serialized request DTO
public int? Identificador { get; set; } // ID of the affected record (nullable)
}
Audit Log Fields
| Field | Type | Description |
|---|
Id | int | Auto-increment primary key |
DireccionIP | string | IP address of the calling client |
Usuario | string | Username from the DTO (e.g., pacienteDTO.UsuarioCreacion) |
Mensaje | string | The JsonResponse.Message returned to the client |
Controlador | string | Module identifier string from Mensajes (e.g., "Usuario") |
Accion | string | Operation name: "Add", "Update", "Delete", "Login" |
FechaRegistro | DateTime | Timestamp of the action, typically set by a SQL DEFAULT GETDATE() |
Objeto | string | Full JSON serialization of the DTO that was sent (via JsonConvert.SerializeObject) |
Identificador | int? | Primary key of the affected row (0 for inserts before the ID is known) |
Writing an Audit Record
The LogBL singleton provides a single Add method:
public class LogBL : Singleton<LogBL>, ILogBL<Log>
{
public int Add(Log entity)
{
return LogRepository.Instancia.Add(entity);
}
}
Controllers call LogBL.Instancia.Add(new Log { … }) inside the try block, after the primary business operation completes, so that the audit record captures the real outcome — including any warning message:
[HttpPost]
public JsonResponse Add(ADM_PACIENTEDTO pacienteDTO)
{
var jsonResponse = new JsonResponse { Success = true };
try
{
var paciente = MapperHelper.Map<ADM_PACIENTEDTO, ADM_PACIENTE>(pacienteDTO);
// … business logic …
// Audit record written regardless of Success/Warning outcome
LogBL.Instancia.Add(new Log
{
Accion = Mensajes.Add, // "Add"
Controlador = Mensajes.UsuarioController, // "Usuario"
Identificador = 0,
Mensaje = jsonResponse.Message,
Usuario = pacienteDTO.UsuarioCreacion,
Objeto = JsonConvert.SerializeObject(pacienteDTO)
});
}
catch (Exception ex)
{
LogError(ex); // log4net — stack trace to file
jsonResponse.Success = false;
jsonResponse.Message = Mensajes.IntenteloMasTarde;
}
return jsonResponse;
}
Every Add, Update, Delete, and Login operation writes an audit record to the database, even when the operation returns a business warning (e.g., duplicate record). This means the audit table captures all attempts, not just successful ones. Exception failures are recorded by log4net only (to Log/Log.txt), since the LogBL.Instancia.Add call is inside the try block and would not execute if the exception occurs before it.
Action Name Constants
The Mensajes class defines string constants used for the Accion field:
public static string Add = "Add";
public static string Update = "Update";
public static string Delete = "Delete";
public static string Login = "Login";
public static string AddDetalleGrupal = "AddDetalleGrupal";
Comparing the Two Mechanisms
| Aspect | log4net (Log/Log.txt) | Database Audit Log |
|---|
| Triggered by | Unhandled exceptions in catch block | Every CRUD/Login action in try block |
| Storage | Rolling text file on IIS server | Log table in SQL Server |
| Queryable | No (text file) | Yes (SQL SELECT) |
| Contains stack trace | Yes | No |
| Contains request payload | No | Yes (JSON-serialized DTO) |
| Survives server restart | Yes (persistent file) | Yes (persistent database) |
| Purpose | Developer/ops incident investigation | Clinical compliance and audit trail |
Set up a scheduled job or SQL Agent task to archive or purge rows from the Log audit table older than a compliance-defined retention period (e.g., 5 years for Peruvian clinical records). The FechaRegistro column is the natural partition key for this archival process.