我正在开发一个 ASP.NET Core 6 MVC 应用程序“AzureLogging”,该应用程序测试使用 NLog 将日志写入 Azure Blob 存储。我遇到了无法在 Azure Blob 存储中存储日志文件的问题,即使 NLog 完美运行本地机器。
这是我的设置和测试步骤:
Blob 存储已在 Azure 门户中设置,并成功测试了所有文件操作:读取、上传、下载和删除。
在MVC应用程序中,加载以下包(参见下面的代码段#1)
设置 NLog.config 文件,包括 Azure 中的日志记录目标(请参阅下面的代码段 #2)
在program.cs文件中,指定使用NLog作为日志记录提供程序(请参阅下面的代码段#3)
为了确保 Blob 连接字符串和存储访问正常工作,我添加了在 MVC 应用程序中执行文件操作的操作:列出文件、上传和删除。他们工作得很好。 (参见下面的代码段#4)
问题描述
Nlog 使用与 MVC 应用程序中执行文件操作的操作相同的 Blob 存储连接字符串、帐户名和访问密钥。当日志记录目标更改为“azure”时,没有日志文件写入 Blob 存储。
我还将Nlog内部日志记录级别设置为“Trace”,并检查了内部日志文件。没有发现明显错误
到目前为止,我还无法确定根本原因是什么。我将不胜感激任何建议或故障排除建议。
代码#1:加载的包
<PackageReference Include="Azure.Storage.Blobs" Version="12.18.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="NLog" Version="5.2.5" />
<PackageReference Include="NLog.Extensions.AzureBlobStorage" Version="4.3.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.5" />
代码#2 Nlog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Trace"
internalLogFile="c:\temp\internal-nlog-AspNetCore.txt">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="NLog.Extensions.AzureStorage"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
<target xsi:type="Console" name="consoleTarget" layout="${MicrosoftConsoleLayout}" />
<!-- File target for output app logs on local machine-->
<target xsi:type="File" name="webLogTarget" fileName="c:\temp\logs\AzureLogging\AzureLogging_${shortdate}.log"
layout="${longdate} ${level:uppercase=true} ${callsite} ${message}"/>
<!-- Azure blob storage target for output app logs to Azure storage -->
<target xsi:type="AzureBlobStorage"
name="azure"
connectionString="DefaultEndpointsProtocol=https; AccountName=mdxstorage1; AccountKey=a/g/KptWTDUpY76/dZQYBkqmVB+CgjlgRw4LM7kb1pxMIlZkvg32x/ifbMtFh9uY9wRUoX6DxQSu+AStK//VEg==; EndpointSuffix=core.windows.net"
containerName="mdxweblogs"
blobName="AzureLogging_${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="Microsoft.AspNetCore.*" level="Warn" writeTo="consoleTarget" final="true" />
<logger name="AzureLogging.*" minlevel ="Trace" writeTo="azure" />
</rules>
</nlog>
代码#3:program.cs文件
using NLog;
using NLog.Web;
// Early init of NLog to allow startup and exception logging, before host is built
var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Host.UseNLog();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
代码#4:StorageController.cs
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using AzureLogging.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using NLog;
namespace AzureLogging.Controllers
{
public class StorageController : Controller
{
private readonly ILogger<StorageController> _logger;
private readonly string _stgConnString;
private readonly string _stgContainer;
public StorageController(ILogger<StorageController> logger)
{
_logger = logger;
_stgConnString = "DefaultEndpointsProtocol=https;AccountName=mdxstorage1;AccountKey=a/g/KptWTDUpY76/dZQYBkqmVB+CgjlgRw4LM7kb1pxMIlZkvg32x/ifbMtFh9uY9wRUoX6DxQSu+AStK//VEg==;EndpointSuffix=core.windows.net";
_stgContainer = "mdxweblogs";
}
public IActionResult Index()
{
return View("ListFiles");
}
public IActionResult ListFiles()
{
BlobStgViewModel viewModel = new();
try
{
_logger.LogInformation("List files in Azure Blob Storage");
viewModel.Container = _stgContainer;
BlobContainerClient cntClient = new BlobContainerClient(_stgConnString, _stgContainer);
foreach(BlobItem blob in cntClient.GetBlobs())
{
viewModel.BlobList.Add(blob.Name);
}
}
catch (Exception ex)
{
throw new ApplicationException("Error occurred when listing files in Azure Blob Storage");
}
return View(viewModel);
}
public IActionResult UploadFile()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile mediaFile)
{
try
{
_logger.LogInformation($"Upload file {mediaFile.Name} to Azure Blob storage");
if (mediaFile is not null && (!string.IsNullOrEmpty(mediaFile.Name)))
{
BlobContainerClient cntClient = new BlobContainerClient(_stgConnString, _stgContainer);
// Initialize BlobClient with the uploaded file name
var blobClient = cntClient.GetBlobClient(mediaFile.FileName);
// Get stream from uploaded file
using (var stream = mediaFile.OpenReadStream())
{
// Upload the stream to Azure Blob storage asynchronously
await blobClient.UploadAsync(stream);
}
return RedirectToAction("ListFiles");
}
else
{
return View();
}
}
catch (Exception ex)
{
throw new ApplicationException("Error occurred when listing files in Azure Blob Storage");
}
}
public IActionResult DeleteFile()
{
BlobStgViewModel viewModel = new();
try
{
BlobContainerClient cntClient = new BlobContainerClient(_stgConnString, _stgContainer);
foreach (var blobItem in cntClient.GetBlobs())
{
viewModel.SelectionList.Add(new SelectListItem(blobItem.Name, blobItem.Name ));
}
}
catch(Exception ex)
{
throw new ApplicationException("Error occurred when retrieving files from storage");
}
return View(viewModel);
}
[HttpPost]
public IActionResult DeleteFile(string selectedItem)
{
try
{
_logger.LogInformation($"Delete file {selectedItem} from Azure Blob Storage");
BlobContainerClient cntClient = new BlobContainerClient(_stgConnString, _stgContainer);
BlobClient blobClient = cntClient.GetBlobClient(selectedItem);
blobClient.Delete();
return RedirectToAction("ListFiles");
}
catch (Exception ex)
{
throw new ApplicationException("Error occurred when delete file from storage");
}
return View();
}
}
}
通过将 Nlog.extensions.AzureStorage 包替换为 NLog.extensions.AzureBlobStorage 解决了该问题。 NLog.Config 使用 Blob 存储连接字符串和容器名称来指定 Blob 存储作为日志记录