Open soul-a opened 1 year ago
Bom dia... poderia nos mostrar como está o seu provider de log? Acredito que o problema esteja nele
Bom dia, segue abaixo o provider usado, dentro do DispatchLogCache
do log eu chamo um service que registra os dados no banco, estou usando o Firebird v4.0.
unit Providers.Logger.Database;
interface
uses
System.Classes,
Horse.Logger;
type
TLoggerDatabaseConfig = class
{ private declarations }
private
FLogFormat: string;
{ public declarations }
public
constructor Create;
function SetLogFormat(ALogFormat: string): TLoggerDatabaseConfig;
function GetLogFormat(out ALogFormat: string): TLoggerDatabaseConfig;
class function New: TLoggerDatabaseConfig;
end;
TLoggerProviderDatabaseManager = class(THorseLoggerThread)
{ private declarations }
private
FConfig: TLoggerDatabaseConfig;
{ protected declarations }
protected
procedure DispatchLogCache; override;
{ public declarations }
public
destructor Destroy; override;
function SetConfig(AConfig: TLoggerDatabaseConfig): TLoggerProviderDatabaseManager;
end;
TLoggerProviderDatabase = class(TInterfacedObject, IHorseLoggerProvider)
private
{ private declarations }
FLoggerProviderDatabaseManager: TLoggerProviderDatabaseManager;
protected
{ protected declarations }
public
{ public declarations }
constructor Create(const AConfig: TLoggerDatabaseConfig = nil);
destructor Destroy; override;
procedure DoReceiveLogCache(ALogCache: THorseLoggerCache);
class function New(const AConfig: TLoggerDatabaseConfig = nil): IHorseLoggerProvider;
end;
implementation
uses System.SysUtils, System.JSON, System.SyncObjs, Services.Logger.Database;
{ THorseLoggerProviderDatabase }
const
DEFAULT_LOG_FORMAT =
'${time}, ${time_short}, ${execution_time}, ${request_clientip}, ${request_method}, ' +
'${request_version}, ${request_url}, ${request_query}, ${request_path_info}, ' +
'${request_path_translated}, ${request_cookie}, ${request_accept}, ${request_from}, ' +
'${request_host}, ${request_referer}, ${request_user_agent}, ${request_connection}, ' +
'${request_remote_addr}, ${request_remote_host}, ${request_script_name}, ${request_server_port}, ' +
'${request_authorization}, ${request_content_encoding}, ${request_content_type}, ' +
'${request_content_length}, ${request_content_version}, ${request_content}, ' +
'${response_server}, ${response_allow}, ${response_location}, ${response_content_encoding}, ' +
'${response_content_type}, ${response_content_length}, ${response_content}, ${response_status}';
constructor TLoggerProviderDatabase.Create(const AConfig: TLoggerDatabaseConfig);
begin
FLoggerProviderDatabaseManager := TLoggerProviderDatabaseManager.Create(True);
FLoggerProviderDatabaseManager.SetConfig(AConfig);
FLoggerProviderDatabaseManager.FreeOnTerminate := False;
FLoggerProviderDatabaseManager.Start;
end;
destructor TLoggerProviderDatabase.Destroy;
begin
FLoggerProviderDatabaseManager.Terminate;
FLoggerProviderDatabaseManager.GetEvent.SetEvent;
FLoggerProviderDatabaseManager.WaitFor;
FLoggerProviderDatabaseManager.Free;
inherited;
end;
procedure TLoggerProviderDatabase.DoReceiveLogCache(ALogCache: THorseLoggerCache);
var
I: Integer;
begin
for I := 0 to Pred(ALogCache.Count) do
FLoggerProviderDatabaseManager.NewLog(THorseLoggerLog(ALogCache.Items[0].Clone));
end;
class function TLoggerProviderDatabase.New(const AConfig: TLoggerDatabaseConfig): IHorseLoggerProvider;
begin
Result := TLoggerProviderDatabase.Create(AConfig);
end;
{ TLoggerProviderDatabaseManager }
destructor TLoggerProviderDatabaseManager.Destroy;
begin
FreeAndNil(FConfig);
inherited;
end;
procedure TLoggerProviderDatabaseManager.DispatchLogCache;
var
I, Z: Integer;
LLogCache: THorseLoggerCache;
LLog: THorseLoggerLog;
LParams: TArray<string>;
LValue: string;
LLogStr: string;
Service: TServiceLoggerDatabase;
begin
if FConfig = nil then
FConfig := TLoggerDatabaseConfig.New;
Service := TServiceLoggerDatabase.Create;
FConfig.GetLogFormat(LLogStr);
LLogCache := ExtractLogCache;
try
if LLogCache.Count = 0 then
Exit;
{ Percorre o LOG com base no formato predefindo }
for I := 0 to Pred(LLogCache.Count) do
begin
var LLogJSON: TJSONObject;
LLog := LLogCache.Items[I] as THorseLoggerLog;
LParams := THorseLoggerUtils.GetFormatParams(LLogStr);
LLogJSON := TJSONObject.Create;
for Z := Low(LParams) to High(LParams) do
begin
if LLog.TryGetValue<string>(LParams[Z], LValue) then
LLogJSON.AddPair(LParams[Z], LValue);
end;
{ Service para LOG }
Service.ProduceLog(LLogJSON);
{ Free JSON }
LLogJSON.Free;
end;
finally
LLogCache.Free;
FreeAndNil(Service);
end;
end;
function TLoggerProviderDatabaseManager.SetConfig(AConfig: TLoggerDatabaseConfig): TLoggerProviderDatabaseManager;
begin
Result := Self;
FConfig := AConfig;
end;
{ TLoggerDatabaseConfig }
constructor TLoggerDatabaseConfig.Create;
begin
FLogFormat := DEFAULT_LOG_FORMAT;
end;
function TLoggerDatabaseConfig.GetLogFormat(out ALogFormat: string): TLoggerDatabaseConfig;
begin
Result := Self;
ALogFormat := FLogFormat;
end;
class function TLoggerDatabaseConfig.New: TLoggerDatabaseConfig;
begin
Result := TLoggerDatabaseConfig.Create;
end;
function TLoggerDatabaseConfig.SetLogFormat(ALogFormat: string): TLoggerDatabaseConfig;
begin
Result := Self;
FLogFormat := ALogFormat;
end;
end.
Fico a disposição para mais detalhes, agradeço.
Obs: Já realizei testes isolados usando o outros provider's, inclusive os oficiais fornecidos pelo middleware de logger e o problema é o mesmo, em pesquisar a outros lib's que utilizam middlewares para log, o mesmo possuem finalizações especificas de seus log's quando feito o deploy para IS_API DLL.
Edit 1 (05/02/2024 10:26):
Boa tarde... acharam alguma solução para o problema em questão? Aqui nos também utilizamos o logger inclusive com o provider oficial de salvar em arquivo texto, compilando para o IIS em modo 64 bits e não temos esse tipo de comportamento. Precisava analisar algo mais próximo do cenário de vocês. Até porque até então, ninguém mais reclamou do problema.
Possuo algumas aplicações no ambiente ISAPI e funcionam normalmente, porém ao tentar dar recycle do pool da aplicação, o pool só é reciclado quando o timeout de "Desligamento" é atingido, durante testes internos notei que o problema estava no Horse.Logger.
Aparentemente a aplicação não está limpando as threads, fiz diversas tentativas diretamente no Horse.Provider.ISAPI, porém não obtive sucesso, deixarei abaixo uma das tentativas que tentei usar para limpar as threads
O log interno acima, acusa que ele está limpando a thread manager, porém a aplicação não termina o recycle mesmo assim.
Fiz algumas pesquisas relacionadas a ThreadPool no IIS e vi que é uma boa prática finalizar as therads no método
TISAPIApplication.OnTerminate
ou no método de exportTerminateExtension
.Dependências usadas (apenas as relacionadas a issue)
O provider para o logger é interno, foi criado baseado no provider horse-logger-provider-logfile e horse-logger-provider-console
Links relacionados