Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Após analise de como o log era gerado optou-se por modificar os logs, para que os mesmos sejam menos verbosos, mais assertivos e também contenham mais informação.

O APPSettings mudou para

Bloco de código
languagec#
themeMidnight
titleappsettings
    "Serilog": {
        "MinimumLevel": {
            "Default": "Information",
            "Override": {
                "Microsoft": "Warning",
                "System": "Warning",
                "Tnf": "Warning"
            }
        },

Podemos notar acima que apenas o default está como information enquanto os outros logs estão com warning, e incluimos o tnf também como warning isso tornou o log menos verboso.

No startup fizemos alterações conforme abaixo:

Image Removed

Image Removed

Image Removed

Seguindo o program alterações abaixo:

Image Removed

Alterações no log dentro do controller

Bloco de código
languagec#
themeMidnight
titleController
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Office2010.Excel;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using PDVCore.Lib.Models.ViewModels;
using PDVSync.Core.Produto.Application.Services.Interfaces;
using PDVSync.Core.Produto.Dto.DadoDinamico;
using PDVSync.Core.Produto.Dto.Produto;
using PDVSync.Core.Produto.WebApi.V3.webConstants.pdvsyncclient;
using Serilog.Context;

namespace PDVSync.Core.Produto.WebApi.V3.Controllers.pdvsyncclient
{
    [Route(WebConstants.ProdutoRouteName)]
    [Route(WebConstants.ProdutoRouteNameVersion)]
    [ApiController]
    [ApiVersion("3.0")]
    [Produces("application/json")]
    [Consumes("application/json")]

    public class ProdutoController : TnfController
    {
        private const string _name = "Produto";

        private readonly ILogger<ProdutoController> _logger;
        private readonly IDadoDinamicoAppService _dadoDinamicoAppService;

        public ProdutoController(ILogger<ProdutoController> logger, IDadoDinamicoAppService dadoDinamicoAppService)
        {
            _logger = logger;
            _dadoDinamicoAppService = dadoDinamicoAppService;

        }


        /// <summary>
        /// Get Cliente
        /// </summary>
        /// <param name="idInquilino">Inquilino id do inquilino</param>
        /// <param name="lote">Request params</param>
        /// <param name="qtdRegistros">Request params</param>
        /// <param name="sequencial">Request params</param>
        /// <param name="listIdProprietario">Request params</param>
        /// <returns>Cliente requested</returns>
        [MapToApiVersion("3.0")]
        [HttpGet("{idInquilino}/{lote}/{qtdRegistros}/{sequencial}")]
        [ProducesResponseType(typeof(ResultViewModel<List<DadoDinamicoDto>>), 200)]
        [ProducesResponseType(typeof(BadRequestObjectResult), 400)]
        [TnfRoleAuthorize(ApiConstants.Authorizations.Profiles.PDVSync_Client)]
        public async Task<IActionResult> GetAllAsync(string idInquilino,
                     string lote,
                     int qtdRegistros,
                     int sequencial,
                     [FromQuery] List<string> listIdProprietario)
        {
            using var apiVersionContext = LogContext.PushProperty("APIVersion", 3); // A adição de campos como esse geram dados no log que é enviado para o grafana!!!
            using var inquilinoContext = LogContext.PushProperty("IdInquilino", idInquilino);
            using var loteContext = LogContext.PushProperty("Lote", lote);
            using var qtdRegistrosContext = LogContext.PushProperty("qtdRegistros", qtdRegistros);
            using var sequencialContext = LogContext.PushProperty("sequencial", sequencial);

            _logger.LogInformation($"Iniciando atualização do {_name}.");
            var stopwatch = new Stopwatch();

            try
            {
                if (string.IsNullOrEmpty(idInquilino) ||
                    string.IsNullOrEmpty(lote) ||
                    listIdProprietario != null && listIdProprietario.Count <= 0)
                {
                    _logger.LogWarning(_name + " com ID {ProdutoId} não foi localizado.", idInquilino);
                    return BadRequest();
                }

                var listProdutoDto = await _dadoDinamicoAppService.GetListaBaixaAsync(12,
                    idInquilino,
                    lote,
                    qtdRegistros,
                    sequencial,
                    listIdProprietario);
                stopwatch.Stop();

                using var tempoTotalContext = LogContext.PushProperty("ElapsedMilliseconds", stopwatch.ElapsedMilliseconds);
                if (listProdutoDto == null || listProdutoDto.Count <= 0)
                {
                    using var registrosRetornadosContext = LogContext.PushProperty("RegistrosRetornados", 0);

                    return Ok(new ResultViewModel<List<DadoDinamicoDto>>()
                    {

                        Success = false,
                        Message = "Nenhum registro encontrado"
                    });
                }
                int registrosRetornados = listProdutoDto?.Count ?? 0;
                var loteOrigem = listProdutoDto?.FirstOrDefault()?.LoteOrigem;
                if (!string.IsNullOrEmpty(loteOrigem))
                {
                    using var loteOrigemContext = LogContext.PushProperty("LoteOrigem", loteOrigem);
                    using var registrosRetornadosContext = LogContext.PushProperty("RegistrosRetornados", registrosRetornados);
                }

                _logger.LogInformation($"Busca de de {_name} finalizada com sucesso.");
                return Ok(new ResultViewModel<List<DadoDinamicoDto>>()
                {
                    Success = true,
                    Message = "",
                    Data = listProdutoDto.ToList(),
                    TotalTime = stopwatch.ElapsedMilliseconds,
                    NumberOfRecords = listProdutoDto.Count()
                });
            }
            catch (Exception ex)
            {
                _logger.LogError("Erro ao buscar Produtos. | Método: "
                    + System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "." + System.Reflection.MethodBase.GetCurrentMethod().Name
                    + " | Erro: "
                    + ex.Message);

                return BadRequest("Erro ao buscar Produtos: " + ex.Message);
            }
        }
    }
}

A adição de pushproperty no log context faz com que a informação seja colocada em uma coluna do log. Importante salientar que o information que vai após o log vai carregar todos os properties anteriores, portando os que são adicionados depois vão no proximo information ou error.

Importante que qualquer informação colocada no pushproperty tem que estar no schema que vou adicionar abaixo:

Bloco de código
languagetext
themeMidnight
titleSchema json

[
  {"name": "partition_time", "type": "TIMESTAMP"},
  {"name": "Timestamp","type": "TIMESTAMP","mode": "NULLABLE","description": "Timestamp of the log entry."},
  {"name": "Level","type": "STRING","mode": "NULLABLE","description": "Log level (e.g., Information, Error, Warning)."},
  {"name": "MessageTemplate","type": "STRING","mode": "NULLABLE","description": "Template for the log message."},
  {"name": "Exception","type": "STRING","mode": "NULLABLE","description": "Exception details, if any."},
  {"name": "Properties","type": "RECORD","mode": "NULLABLE","fields":   [
                {"name": "SourceContext","type": "STRING","mode": "NULLABLE"},
                {"name": "Application","type": "STRING","mode": "NULLABLE"},
                {"name": "Area","type": "STRING","mode": "NULLABLE"},
                {"name": "Enviroment","type": "STRING","mode": "NULLABLE"},
                {"name": "Service","type": "STRING","mode": "NULLABLE"},
                {"name": "Software","type": "STRING","mode": "NULLABLE"},
                {"name": "CpuUsagePercent","type": "FLOAT","mode": "NULLABLE"},
                {"name": "MemoryUsageMB","type": "FLOAT","mode": "NULLABLE"},
                {"name": "MemoryUsagePercent","type": "FLOAT","mode": "NULLABLE"},
                {"name": "ApplicationName","type": "STRING","mode": "NULLABLE"},
                {"name": "RequestHost","type": "STRING","mode": "NULLABLE"},
                {"name": "UserAgent","type": "STRING","mode": "REPEATED"},
                {"name": "ClientIp","type": "STRING","mode": "NULLABLE"},
                {"name": "RequestMethod","type": "STRING","mode": "NULLABLE"},
                {"name": "RequestPath","type": "STRING","mode": "NULLABLE"},
                {"name": "StatusCode","type": "INTEGER","mode": "NULLABLE"},
                {"name": "Elapsed","type": "FLOAT","mode": "NULLABLE"},
                {"name": "RequestId","type": "STRING","mode": "NULLABLE"},
                {"name": "ConnectionId","type": "STRING","mode": "NULLABLE"},
                {"name": "AuthenticationScheme","type": "STRING","mode": "NULLABLE"},
                {"name": "FailureMessage","type": "STRING","mode": "NULLABLE"},
                {"name": "EventId","type": "RECORD","mode": "NULLABLE","fields":[
                        {"name": "Id","type": "INTEGER","mode": "NULLABLE"},
                        {"name": "Name","type": "STRING","mode": "NULLABLE"}]},
                {"name": "ActionId","type": "STRING","mode": "NULLABLE"},
                {"name": "ActionName","type": "STRING","mode": "NULLABLE"},
                {"name": "RegistrosRecebidos","type": "INTEGER","mode": "NULLABLE"},
                {"name": "LoteOrigem","type": "STRING","mode": "NULLABLE"},
                {"name": "IdInquilino","type": "STRING","mode": "NULLABLE"},
                {"name": "APIVersion","type": "INTEGER","mode": "NULLABLE"},
                {"name": "RegistrosCount","type": "INTEGER","mode": "NULLABLE"},
                {"name": "Elapsedms","type": "FLOAT","mode": "NULLABLE"},
                {"name": "ElapsedMilliseconds","type": "INTEGER","mode": "NULLABLE"},
                {"name": "RegistrosProcessados","type": "INTEGER","mode": "NULLABLE"},
                {"name": "Inquilino","type": "STRING","mode": "NULLABLE"},
                {"name": "RegistrosRetornados","type": "INTEGER","mode": "NULLABLE"},
                {"name": "Lote","type": "STRING","mode": "NULLABLE"},
                {"name": "sequencial","type": "INTEGER","mode": "NULLABLE"},
                {"name": "qtdRegistros","type": "INTEGER","mode": "NULLABLE"},
                {"name": "DataBusca","type": "STRING","mode": "NULLABLE"}
        ]},
        {"name": "Renderings","type": "RECORD","mode": "NULLABLE","fields": [
                {"name": "Elapsed","type": "RECORD","mode": "REPEATED","fields": [
                        {"name": "Format","type": "STRING","mode": "NULLABLE"},
                        {"name": "Rendering","type": "STRING","mode": "NULLABLE"}
                ]},
                {"name": "Elapsedms","type": "RECORD","mode": "REPEATED","fields": [
                        {"name": "Format","type": "STRING","mode": "NULLABLE"},
                        {"name": "Rendering","type": "STRING","mode": "NULLABLE"}
                ]}
        ]}
]

Importante colocar os pushProperties, principalmente com as informações relevantes que existirem no momento, como por exemplo inquilino, lote origem, lote registros recebidos, registros processados e registros retornados.