C# 使用Nlog从Lambda进行Cloudwatch日志记录创建只读文件系统例外

C# 使用Nlog从Lambda进行Cloudwatch日志记录创建只读文件系统例外,c#,.net-core,aws-lambda,amazon-cloudwatch,nlog,C#,.net Core,Aws Lambda,Amazon Cloudwatch,Nlog,我在登录到cloudwatch时遇到问题,因为它看起来是间歇性的。并非所有错误都记录到Cloudwatch,我在默认的lambda日志组中获得只读文件系统异常 该系统的体系结构涉及一个lambda(dotnetcore2.1),由一个SQS队列触发并从中接收消息。然后lambda向第三方发出http请求,并将响应上传到S3。队列上一次有1000多条消息,我已经将lambdas reserved concurrency设置为100,以处理这个问题,一次处理1条记录,这一切看起来都很好 我正在使用N

我在登录到cloudwatch时遇到问题,因为它看起来是间歇性的。并非所有错误都记录到Cloudwatch,我在默认的lambda日志组中获得只读文件系统异常

该系统的体系结构涉及一个lambda(dotnetcore2.1),由一个SQS队列触发并从中接收消息。然后lambda向第三方发出http请求,并将响应上传到S3。队列上一次有1000多条消息,我已经将lambdas reserved concurrency设置为100,以处理这个问题,一次处理1条记录,这一切看起来都很好

我正在使用Nlog格式化和过滤lambda中的日志记录,下面的配置显示我只有awstarget,没有文件系统目标。我添加了异步包装器,试图阻止这些问题,但仍然没有成功

<?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"
      throwConfigExceptions="true">
  <extensions>
    <add assembly="NLog.AWS.Logger" />
  </extensions>
  <targets>
    <target name="CloudwatchTraceTargetAsync" xsi:type="AsyncWrapper" overflowAction="Block">
      <target name="CloudwatchTraceTarget" type="AWSTarget" logGroup="/aws/lambda/adx-dev-batch-processor-consumer-trace" region="eu-west-2" layout="${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}"/>
    </target>
    <target name="CloudwatchErrorTargetAsync" xsi:type="AsyncWrapper" overflowAction="Block">
      <target name="CloudwatchErrorTarget" type="AWSTarget" logGroup="/aws/lambda/adx-dev-batch-processor-consumer-error" region="eu-west-2" layout="${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}"/>
    </target>
  </targets>
  <rules>
    <logger name="*" minlevel="Trace" maxlevel="Trace" writeTo="CloudwatchTraceTargetAsync" enabled="false" />
    <logger name="*" minlevel="Error" maxlevel="Error" writeTo="CloudwatchErrorTargetAsync" enabled="true" />
  </rules>
</nlog>

lambda的入口点如下所示。我正在将记录器正常地注入到我的每个服务和日志中

 public class QueueConsumerLambda
    {
        private const string AspnetCoreEnvironmentVariable = "ASPNETCORE_ENVIRONMENT";
        private IServiceProvider _serviceProvider;

        [LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
        public async Task ProcessQueueMessage(SQSEvent sqsEvent, ILambdaContext context)
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var environmentName = Environment.GetEnvironmentVariable(AspnetCoreEnvironmentVariable);

            LogManager.Configuration = new XmlLoggingConfiguration($"nlog.Consumer.{environmentName}.config");

            var logger = LogManager.GetCurrentClassLogger();
            try
            {
                logger.Trace($"QueueConsumer.ProcessQueueMessage - started with {sqsEvent.Records.Count} records.");

                var config = new ConfigurationBuilder()
                    .SetBasePath(Environment.CurrentDirectory)
                    .AddJsonFile($"appsettings.{environmentName}.json", false, false)
                    .AddEnvironmentVariables()
                    .Build();

                _serviceProvider = ConfigureServices(config);

                var dataRetrievalController = _serviceProvider.GetRequiredService<QueueConsumerController>();

                foreach (var record in sqsEvent.Records)
                {
                    logger.Trace($"QueueConsumer.ProcessQueueMessage - messageId: {record.MessageId}, eventSource: {record.EventSource}, record.Body: {record.Body}");

                    var messageBody = JsonConvert.DeserializeObject<SqsMessageModel>(record.Body);

                    await dataRetrievalController.GetData(messageBody, record.ReceiptHandle);
                }

                stopwatch.Stop();
                logger.Trace($"QueueConsumer.ProcessQueueMessage - finished and it took {stopwatch.Elapsed.Seconds} seconds.");
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Stopped program because of exception");
            }
            finally
            {
                LogManager.Shutdown();
            }
        }
        private static IServiceProvider ConfigureServices(IConfiguration config)
        {
            var services = new ServiceCollection()
                .AddLogging(loggingBuilder =>
                {
                    // configure Logging with NLog
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddConfiguration(config.GetSection("Logging"));
                    loggingBuilder.AddNLog(config);
                })

                // registering more services
        }
    }
公共类QueueConsumerLambda
{
私有常量字符串AspnetCoreEnvironmentVariable=“ASPNETCORE\u环境”;
私人IServiceProvider_服务提供商;
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.Json-serializer))]
公共异步任务ProcessQueueMessage(SQSEvent SQSEvent,ILambdaContext上下文)
{
var stopwatch=新秒表();
秒表。开始();
var environmentName=Environment.GetEnvironmentVariable(AspnetCoreEnvironmentVariable);
LogManager.Configuration=newXMLLoggingConfiguration($“nlog.Consumer.{environmentName}.config”);
var logger=LogManager.GetCurrentClassLogger();
尝试
{
Trace($“QueueConsumer.ProcessQueueMessage-以{sqsEvent.Records.Count}记录开始。”);
var config=new ConfigurationBuilder()
.SetBasePath(环境.CurrentDirectory)
.AddJsonFile($“appsettings.{environmentName}.json”,false,false)
.AddenEnvironmentVariables()
.Build();
_serviceProvider=ConfigureServices(配置);
var dataRetrievalController=_serviceProvider.GetRequiredService();
foreach(sqsEvent.Records中的var记录)
{
logger.Trace($“QueueConsumer.ProcessQueueMessage-messageId:{record.messageId},eventSource:{record.eventSource},record.Body:{record.Body}”);
var messageBody=JsonConvert.DeserializeObject(record.Body);
等待dataRetrievalController.GetData(messageBody、record.ReceiptHandle);
}
秒表;
Trace($“QueueConsumer.ProcessQueueMessage-已完成,花费了{stopwatch.appeased.Seconds}秒。”);
}
捕获(例外情况除外)
{
logger.Error(例如,“由于异常而停止程序”);
}
最后
{
LogManager.Shutdown();
}
}
专用静态IServiceProvider配置服务(IConfiguration配置)
{
var services=newservicecolection()
.AddLogging(loggingBuilder=>
{
//使用NLog配置日志记录
loggingBuilder.ClearProviders();
loggingBuilder.AddConfiguration(config.GetSection(“Logging”);
loggingBuilder.AddNLog(配置);
})
//注册更多服务
}
}
我正在成功地将日志放入单独的错误日志组,但不是全部日志。有些错误没有被记录下来,我知道这是因为http请求的预期输出文件不在S3中,当我在本地调试时,我遇到了预期的异常。我唯一的猜测是,正在记录到默认日志组的只读文件系统错误是一种症状。还值得注意的是,并非总是会丢失相同的错误,如果我在第二天处理相同的请求,则不会记录不同数量的错误


我很困惑,不确定是否在lambda函数的上下文中正确设置了日志记录,或者是否达到了cloudwatch限制或任何其他原因。因此,任何见解都值得赞赏。如果需要更多信息,请告诉我

我可能会更改它,以便由构造函数负责设置日志记录。不具有请求功能:

公共类QueueConsumerLambda
{
私有常量字符串AspnetCoreEnvironmentVariable=“ASPNETCORE\u环境”;
私人IServiceProvider_服务提供商;
专用非直瞄记录器(NLog.Logger);;
公共队列ConsumerLambda()
{
尝试
{
var environmentName=Environment.GetEnvironmentVariable(AspnetCoreEnvironmentVariable);
LogManager.Configuration=newXMLLoggingConfiguration($“nlog.Consumer.{environmentName}.config”);
_logger=LogManager.GetCurrentClassLogger();
var config=new ConfigurationBuilder()
.SetBasePath(环境.CurrentDirectory)
.AddJsonFile($“appsettings.{environmentName}.json”,false,false)
.AddenEnvironmentVariables()
.Build();
_serviceProvider=ConfigureServices(配置)
}
捕获(例外情况除外)
{
_logger?错误(例如,“由于异常而停止程序”);
_记录器?.LogFactory?.Shutdown();
}
}
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.Json-serializer))]
公共异步任务进程