Skip to content
This repository was archived by the owner on Dec 19, 2025. It is now read-only.

[ADMINAPI-1316] Fix log4net initialization, cross-platform compatibility, and consistent logging#363

Merged
jagudelo-gap merged 5 commits intomainfrom
copilot/fix-f29cc5be-90d6-4e4a-b0ad-e4c457444484
Sep 29, 2025
Merged

[ADMINAPI-1316] Fix log4net initialization, cross-platform compatibility, and consistent logging#363
jagudelo-gap merged 5 commits intomainfrom
copilot/fix-f29cc5be-90d6-4e4a-b0ad-e4c457444484

Conversation

Copy link

Copilot AI commented Sep 28, 2025

Problem

The AdminAPI application was not using log4net properly, causing several issues:

  1. Missing startup logs: Log4net messages in Program.cs (e.g., "Starting Admin API", "Configuration - ApiMode: V2, Engine: SqlServer") were not appearing at application startup
  2. Cross-platform path issues: The application failed to start on Linux/Unix systems due to Windows-style path separators in the log4net configuration path
  3. Console logging not visible: Log messages were not appearing in the console output despite being configured
  4. Inconsistent logging interfaces: RequestLoggingMiddleware used Microsoft.Extensions.Logging.ILogger instead of log4net.ILog

Root Causes

  • Log4net was not initialized before its first use in Program.cs, so early logging calls were lost
  • The appsettings.json configuration used backslash path separators (log4net\\log4net.config) which don't work on Linux/Unix
  • The log4net configuration used TraceAppender instead of ConsoleAppender, making console output invisible
  • File paths used Windows-specific environment variables that don't exist on other platforms
  • Mixed logging interfaces created inconsistent log formatting throughout the application

Solution

This PR implements minimal, surgical fixes to resolve all identified issues:

1. Early Log4net Initialization

Added proper log4net initialization in Program.cs before any logging calls, reading the configuration path from appsettings:

// Initialize log4net early so we can use it in Program.cs
var log4netConfigFileName = builder.Configuration.GetValue<string>("Log4NetCore:Log4NetConfigFileName");
if (!string.IsNullOrEmpty(log4netConfigFileName))
{
    var log4netConfigPath = Path.Combine(AppContext.BaseDirectory, log4netConfigFileName);
    if (File.Exists(log4netConfigPath))
    {
        var log4netConfig = new FileInfo(log4netConfigPath);
        XmlConfigurator.Configure(LogManager.GetRepository(), log4netConfig);
    }
}

2. Cross-Platform Path Compatibility

Fixed path separator in appsettings.json from log4net\\log4net.config to log4net/log4net.config for cross-platform compatibility.

3. Visible Console Logging

Updated log4net.config to use ConsoleAppender instead of TraceAppender and changed the file path to a relative path that works across platforms.

4. Configuration Consistency

Updated the early log4net initialization to read the configuration file path from the Log4NetCore.Log4NetConfigFileName setting, ensuring consistency with the Microsoft.Extensions.Logging.Log4Net.AspNetCore integration.

5. Consistent Log4net Usage

Updated RequestLoggingMiddleware to use log4net's ILog interface instead of Microsoft.Extensions.Logging ILogger<T>, ensuring all logging in the application uses log4net consistently:

private static readonly ILog _logger = LogManager.GetLogger(typeof(RequestLoggingMiddleware));

Verification

  • ✅ Program.cs log4net messages now appear at startup
  • ✅ Console logging works properly on both Windows and Linux
  • ✅ File logging continues to work as expected
  • ✅ Log4net configuration path is consistently read from appsettings.json
  • ✅ RequestLoggingMiddleware now uses log4net ILog with consistent formatting
  • ✅ All logging throughout the application now uses log4net format consistently
  • ✅ All existing unit tests pass
  • ✅ No breaking changes to existing log statements or configuration structure

Impact

This fix ensures that log4net works properly across all supported platforms while maintaining full backward compatibility. The application now has consistent logging throughout, with all components using log4net's ILog interface. The default configuration correctly logs to both console and file as intended, and early startup messages are visible for debugging and monitoring purposes.

Fixes #1316

Original prompt

This section details on the original issue you should resolve

<issue_title>Bug: ADMINAPI-1316 Not using log4net properly</issue_title>
<issue_description>### Issue Description

This application should be using log4net for all of its logging statements. The default configuration should be logging to the Console and to a File.

However, I noticed these observations:

  • The RequestLoggingMiddleware uses ILogger, which comes from Microsoft.Extensions.Logging.
  • There is no dependency injection setting up log4net as the ILogger.
  • The Program.cs has log statements, using Log4net, that do not appear at application startup.

We need to review and fix the log4net setup.

Acceptance Criteria

  • Do not change any log statements, that is, the strings sent to the logger
  • Continue loaded log4net configuration from the log4net.config file

Additional Context

No response</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #362

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: stephenfuqua <9324390+stephenfuqua@users.noreply.github.com>
Copilot AI changed the title [WIP] Bug: [ADMINAPI-1316] Not using log4net properly Fix log4net initialization and cross-platform compatibility Sep 28, 2025
Copilot AI requested a review from stephenfuqua September 28, 2025 13:29
</appender>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<file value="${ProgramData}\Ed-Fi-ODS-AdminAPI\Log.txt" />
<file value="logs/Ed-Fi-ODS-AdminAPI-Log.txt" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is truly a better default option.

var builder = WebApplication.CreateBuilder(args);

// Initialize log4net early so we can use it in Program.cs
var log4netConfigPath = Path.Combine(AppContext.BaseDirectory, "log4net", "log4net.config");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot the log4netConfigPath should be read from the appsettings file, which has Log4NetCore.Log4NetConfigFileName in it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to read the log4net config path from Log4NetCore.Log4NetConfigFileName in appsettings.json instead of hardcoding it. The change ensures consistency with the existing configuration pattern used by the Microsoft.Extensions.Logging.Log4Net.AspNetCore integration. Commit: 0b49c6f

@stephenfuqua
Copy link

@copilot also change RequestLoggingMiddleWare.cs to use Log4net's ILog instead of ILogger, and make sure that Program.cs sets up the ILog dependency injection correctly.

Co-authored-by: stephenfuqua <9324390+stephenfuqua@users.noreply.github.com>
Copilot AI requested a review from stephenfuqua September 28, 2025 13:57
@stephenfuqua stephenfuqua changed the title Fix log4net initialization and cross-platform compatibility [ADMINAPI-1316] Fix log4net initialization and cross-platform compatibility Sep 28, 2025
Co-authored-by: stephenfuqua <9324390+stephenfuqua@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 28, 2025

@copilot also change RequestLoggingMiddleWare.cs to use Log4net's ILog instead of ILogger, and make sure that Program.cs sets up the ILog dependency injection correctly.

Updated RequestLoggingMiddleware to use log4net's ILog interface instead of ILogger<T>. The middleware now uses the static logger pattern (private static readonly ILog _logger = LogManager.GetLogger(typeof(RequestLoggingMiddleware))) consistent with other classes in the codebase. All logging calls have been converted to log4net methods (LogDebug→Debug, LogInformation→Info, LogError→Error) and are now logging with the consistent log4net format. No additional DI setup was needed as the static pattern is used. Commit: e3d2d65

Copilot AI changed the title [ADMINAPI-1316] Fix log4net initialization and cross-platform compatibility Fix log4net initialization, cross-platform compatibility, and consistent logging Sep 28, 2025
}

public async Task Invoke(HttpContext context, ILogger<RequestLoggingMiddleware> logger)
public async Task Invoke(HttpContext context)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This did not use dependency injection, but that's OK in this case, since we're not unit testing logging.

@stephenfuqua
Copy link

This output is much better! Still needs a developer to test the code change thoroughly locally - I only started it up and confirmed the root endpoint works.

Using launch settings from D:\ed-fi\AdminAPI-2.x\Application\EdFi.Ods.AdminApi\Properties\launchSettings.json...
Building...
2025-09-28 16:07:23,461 [1] INFO  Program [(null)] - Starting Admin API
2025-09-28 16:07:23,507 [1] INFO  Program [(null)] - Configuration - ApiMode: V2, Engine: SqlServer
warn: Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer[8]
      The ASP.NET Core developer certificate is not trusted. For information about trusting the ASP.NET Core developer certificate, see https://aka.ms/aspnet/https-trust-dev-cert.
2025-09-28 16:07:24,415 [1] WARN  Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer [(null)] - The ASP.NET Core developer certificate is not trusted. For information about trusting the ASP.NET Core developer certificate, see https://aka.ms/aspnet/https-trust-dev-cert.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:7214
2025-09-28 16:07:24,598 [1] INFO  Microsoft.Hosting.Lifetime [(null)] - Now listening on: https://localhost:7214
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5214
2025-09-28 16:07:24,600 [1] INFO  Microsoft.Hosting.Lifetime [(null)] - Now listening on: http://localhost:5214
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
2025-09-28 16:07:24,605 [1] INFO  Microsoft.Hosting.Lifetime [(null)] - Application started. Press Ctrl+C to shut down.
2025-09-28 16:07:24,608 [1] INFO  Microsoft.Hosting.Lifetime [(null)] - Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\ed-fi\AdminAPI-2.x\Application\EdFi.Ods.AdminApi
2025-09-28 16:07:24,609 [1] INFO  Microsoft.Hosting.Lifetime [(null)] - Content root path: D:\ed-fi\AdminAPI-2.x\Application\EdFi.Ods.AdminApi
2025-09-28 16:08:01,469 [13] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/","traceId":"0HNFUQCBVKUDC:00000001"}
2025-09-28 16:08:02,251 [17] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/favicon.ico","traceId":"0HNFUQCBVKUDC:00000003"}
2025-09-28 16:08:37,586 [17] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/connect/register","traceId":"0HNFUQCBVKUDC:00000005"}
2025-09-28 16:10:23,432 [21] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/connect/register","traceId":"0HNFUQCBVKUDE:00000001"}
2025-09-28 16:09:50,175 [13] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/connect/register","traceId":"0HNFUQCBVKUDD:00000001"}
2025-09-28 16:10:32,102 [20] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/","traceId":"0HNFUQCBVKUDF:00000001"}
2025-09-28 16:12:59,970 [22] INFO  EdFi.Ods.AdminApi.Features.RequestLoggingMiddleware [(null)] - {"path":"/v2/vendors","traceId":"0HNFUQCBVKUDH:00000001"}
2025-09-28 16:13:17,294 [29] INFO  Microsoft.Hosting.Lifetime [(null)] - Application is shutting down...

@stephenfuqua stephenfuqua changed the title Fix log4net initialization, cross-platform compatibility, and consistent logging [ADMINAPI-1316] Fix log4net initialization, cross-platform compatibility, and consistent logging Sep 28, 2025
@stephenfuqua stephenfuqua marked this pull request as ready for review September 28, 2025 21:18
@github-actions
Copy link

Test Results

238 tests   237 ✅  10s ⏱️
  4 suites    1 💤
  4 files      0 ❌

Results for commit 8d47e0b.

@jagudelo-gap jagudelo-gap merged commit 3b621b9 into main Sep 29, 2025
20 checks passed
@jagudelo-gap jagudelo-gap deleted the copilot/fix-f29cc5be-90d6-4e4a-b0ad-e4c457444484 branch September 29, 2025 16:52
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: [ADMINAPI-1316] Not using log4net properly

3 participants