Logování Web API

Běh ABRA API je možné logovat. A to jednak jeho Java část pomocí konfiguračního souboru APIServer.yaml, který je v kořenovém adresáři instalace systému ABRA Gen, a pak dále na úrovni business logiky pomocí souboru NEXUS.CFG.

Součástí obou logů je tzv rid, generované pomocí hlavičky X-Request-ID, které umožňuje snadno identifikovat jak serverovou, tak BO část požadavku v obou takto vytvořených lozích.

Obecná konfigurace nastavení logování systému ABRA Gen viz kap. Logování běhu aplikace.

Doporučená konfigurace nastavení logování na úrovni v souboru NEXUS.CFG je následující:

[Logs]
LogsDirectory=<lokální cesta, ideálně SSD>
Level=3

[Log.ExceptionHook]
Enabled=1
Level=6
ExcludedExceptionClasses=EAbort;NxHiddenError;EIdSocketError;EIdConnectTimeout;EIdNotASocket
ExcludedNxErrorCodes=

[Log.SysLog]
Enabled=1
Level=6

[Log.ProfilingSQL]
Enabled=0
Level=6
Threshold=1000
SQLOutputLength=0

[Log.WAProfilingRequest]
Enabled=1
Level=6
SQLText=1
SQLPlan=1

[Log.WASecurity]
Enabled=1
Level=6

[Log.WAMemory]
Enabled=0
Level=6

[Log.WAPool]
Enabled=0
Level=6

[Log.WASession]
Enabled=0
Level=6

Log ExceptionHook slouží k logování výjimek, je jediný který stojí za to mít zapnutý pořád. Ostatní logy je z důvodu výkonu a rychle rostoucí velikosti souboru s logy mít během provozu vypnuté a zapnout je dle příkladu až při potřebě.

Log SysLog loguje informace ze startu aplikace (tj. s jakými parametry byl program spuštěný, nastavení některých interních proměnný a pod.).

Log Profilingsql na aplikačním serveru loguje SQL dotazy, které překročí nastavený čas. Použitím tohoto logu se dá zjistit, jestli za případnou pomalostí API dotazů nestojí databáze. Threshold je čas v ms, při jehož překročení se dotaz zaloguje. SQLOutputLength je délka SQL dotazu, která se zaloguje, 0 znamená celý dotaz.

Log WAProfilingRequest je nejdůležitější. Je v něm zahrnut buď obsah požadavku i odpověď (Level=6) nebo jen základní informace bez těla požadavku a odpovědi (Level=5). V případě, že provádění požadavku zamrzne, loguje se zde callstack threadu, který požadavek provádí a může napovědět, kde je problém. Od verze 24.1 je log WAProfilingRequest upraven tak, že logování SQL generovaného API se provádí zapnutím přepínače SQLText a nově je možné zalogovat i SQL plán pomocí SQLPlan. SQL plán se nebere přímo z prováděného dotazu, ale požádá se o něj databázový engine v separátním dotazu (implementování na základě informace z AbraBI). Při ladění problémů s rychlostí SQL je doporučeno logování zapnout a vyhodnotit, viz příklady níže.

Log WASecurity umožňuje zjistit, které chráněné objekty byly použity pro získání dat požadavku a tudíž se hodí použít pro řešení problému s právy k objektům.

Příklad volání metody GET pro doklad faktury vydané: GET http://localhost/develop/issuedinvoices, uživatel nemá správně nastavena práva ke chráněným objektům

26.03.2025 11:57:42.847 [5] 00005CF0 (WAProfilingRequest) Request start(rid:API_b144e5342e5d46fe9049cb1494728cb2): GET http://localhost/develop/issuedinvoices
  
  X-Request-ID=API_b144e5342e5d46fe9049cb1494728cb2
  User-Agent=PostmanRuntime/7.43.2
  Host=localhost
  Connection=keep-alive
  Accept=*/*
  Accept-Encoding=gzip, deflate, br
  Postman-Token=20da25f8-eaa4-40ea-b696-f7150f496ce7
  
  
  
26.03.2025 11:57:42.875 [5] 00005CF0 (WASecurity) Add security condition: Field IssuedInvoices.DocQueue_ID(Zdrojová řada)
  Allowed IDs: 5600000101,
  
26.03.2025 11:57:42.877 [5] 00005CF0 (WASecurity) Add security condition: Field IssuedInvoices.AccDocQueue_ID(Účetní řada)
  Allowed IDs: No ID is allowed !!!
  
26.03.2025 11:57:42.879 [5] 00005CF0 (WASecurity) Add security condition: Field IssuedInvoices.BankAccount_ID(Vlastní účet)
  Allowed IDs: 2200000101,
  
26.03.2025 11:57:42.881 [5] 00005CF0 (WASecurity) Add security condition: Field Rows.Division_ID(Středisko)
  Allowed IDs: 2100000101,1200000101,2200000101,1300000101,1400000101,2400000101,3400000101,
  
26.03.2025 11:57:42.884 [5] 00005CF0 (WASecurity) Add security condition: Field Rows.Store_ID(Sklad)
  Allowed IDs: 2100000101,1500000101,2500000101,3500000101,
  
26.03.2025 11:57:42.886 [6] 00005CF0 (WAProfilingRequest) 
  Start read sql - InputParams: @{SelDocQueue_ID1Frag}=('5600000101');@{SelBankAccount_ID3Frag}=('2200000101');@{SelRowsDivision_ID4Frag}=('1300000101','1400000101','3400000101','2400000101','2200000101','1200000101','2100000101');@{SelRowsStore_ID5Frag}=('1500000101','2500000101','3500000101','2100000101');@{$IndexAndWhere}=;
  select T_1.AccDocQueue_ID as F_1$REFERENCE, T_1.AccPresetDef_ID as F_2$REFERENCE, T_1.Address_ID as F_3$REFERENCE, T_1.BankAccount_ID as F_4$REFERENCE, T_1.ClosingPeriod_ID as F_5$REFERENCE, T_1.ConstSymbol_ID as F_6$REFERENCE, T_1.CorrectedBy_ID as F_7$REFERENCE, T_1.Country_ID as F_8$REFERENCE, T_1.CreatedBy_ID as F_9$REFERENCE, T_1.Currency_ID as F_10$REFERENCE, T_1.DealerCategory_ID as F_11$REFERENCE, T_1.DeliveryAddress_ID as F_12$REFERENCE, T_1.DeliveryFirm_ID as F_13$REFERENCE, T_1.DeliveryFirmOffice_ID as F_14$REFERENCE, T_1.DeliveryTerms_ID as F_15$REFERENCE, T_1.DocQueue_ID as F_16$REFERENCE, T_1.Firm_ID as F_17$REFERENCE, T_1.FirmOffice_ID as F_18$REFERENCE, T_1.ID as ID, T_1.IEState_ID as F_19$REFERENCE, T_1.IntrastatDeliveryTerm_ID as F_20$REFERENCE, T_1.IntrastatTransactionType_ID as F_21$REFERENCE, T_1.IntrastatTransportationType_ID as F_22$REFERENCE, T_1.LastPaymentPeriod_ID as F_23$REFERENCE, T_1.LocalZone_ID as F_24$REFERENCE, T_1.ObjVersion as ObjVersion, T_1.PaymentType_ID as F_25$REFERENCE, T_1.Period_ID as F_26$REFERENCE, T_1.Person_ID as F_27$REFERENCE, T_1.PostAddress_ID as F_28$REFERENCE, T_1.PostFirm_ID as F_29$REFERENCE, T_1.PostFirmOffice_ID as F_30$REFERENCE, T_1.TransportationType_ID as F_31$REFERENCE, T_1.VATCountry_ID as F_32$REFERENCE, T_1.Zone_ID as F_33$REFERENCE
  from IssuedInvoices T_1
  where ((T_1.DocQueue_ID IN {SelDocQueue_ID1Frag})) and (((T_1.AccDocQueue_ID IS NULL) OR (T_1.AccDocQueue_ID = '0000000000') OR (T_1.AccDocQueue_ID = ' '))) and ((T_1.BankAccount_ID IN {SelBankAccount_ID3Frag})) and ((EXISTS(SELECT 1 FROM IssuedInvoices2 T_2 WHERE  T_2.Parent_ID =T_1.ID AND ((Division_ID IS NULL) OR (Division_ID = '0000000000') OR (Division_ID = ' ') OR (Division_ID IN {SelRowsDivision_ID4Frag})) AND ((Store_ID IS NULL) OR (Store_ID = '0000000000') OR (Store_ID = ' ') OR (Store_ID IN {SelRowsStore_ID5Frag}))) OR Not EXISTS(SELECT 1 FROM IssuedInvoices2 T_2 WHERE  T_2.Parent_ID =T_1.ID)))
  
26.03.2025 11:57:42.892 [6] 00005CF0 (WAProfilingRequest) Stop read sql duration: 16 ms
26.03.2025 11:57:42.893 [5] 00005CF0 (WAProfilingRequest) Request stop(rid:API_b144e5342e5d46fe9049cb1494728cb2): status 200  time: 0 ms
  
  Link=http://localhost:80/develop/api-docs/swagger.json#; rel="describedBy"
  Content-Type=application/json
  Access-Control-Allow-Credentials=true
  Access-Control-Allow-Origin=*
  Access-Control-Allow-Headers=Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control
  Access-Control-Allow-Methods=GET,PUT,POST,DELETE
  
  []

Logy WAPool, WAMemory a WASession jsou nízkoúrovňové a jejich zapnutí má smysl jen při řešení specifických problémů.