easylogging++.h 277 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852
  1. //
  2. // Easylogging++ v9.80
  3. // Single-header only, cross-platform logging library for C++ applications
  4. //
  5. // Copyright (c) 2015 muflihun.com
  6. //
  7. // This library is released under the MIT Licence.
  8. // http://easylogging.muflihun.com/licence.php
  9. //
  10. // easylogging@muflihun.com
  11. //
  12. // https://github.com/easylogging/easyloggingpp
  13. // http://easylogging.muflihun.com
  14. // http://muflihun.com
  15. //
  16. #ifndef EASYLOGGINGPP_H
  17. #define EASYLOGGINGPP_H
  18. // Compilers and C++0x/C++11 Evaluation
  19. #if defined(__GNUC__)
  20. # define ELPP_COMPILER_GCC 1
  21. # define ELPP_GCC_VERSION (__GNUC__ * 10000 \
  22. + __GNUC_MINOR__ * 100 \
  23. + __GNUC_PATCHLEVEL__)
  24. # if defined(__GXX_EXPERIMENTAL_CXX0X__)
  25. # define ELPP_CXX0X 1
  26. # elif(ELPP_GCC_VERSION >= 40801)
  27. # define ELPP_CXX11 1
  28. # endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
  29. #endif // defined(__GNUC__)
  30. // Visual C++
  31. #if defined(_MSC_VER)
  32. # define ELPP_COMPILER_MSVC 1
  33. # define ELPP_CRT_DBG_WARNINGS 1
  34. # if (_MSC_VER == 1600)
  35. # define ELPP_CXX0X 1
  36. # elif(_MSC_VER >= 1700)
  37. # define ELPP_CXX11 1
  38. # endif // (_MSC_VER == 1600)
  39. #endif // defined(_MSC_VER)
  40. // Clang++
  41. #if defined(__clang__) && (__clang__ == 1)
  42. # define ELPP_COMPILER_CLANG 1
  43. # define ELPP_CLANG_VERSION (__clang_major__ * 10000 \
  44. + __clang_minor__ * 100 \
  45. + __clang_patchlevel__)
  46. # if (ELPP_CLANG_VERSION >= 30300)
  47. # define ELPP_CXX11 1
  48. # endif // (ELPP_CLANG_VERSION >= 30300)
  49. #endif // defined(__clang__) && (__clang__ == 1)
  50. // MinGW
  51. #if defined(__MINGW32__) || defined(__MINGW64__)
  52. # define ELPP_MINGW 1
  53. #endif // defined(__MINGW32__) || defined(__MINGW64__)
  54. // Cygwin
  55. #if defined(__CYGWIN__) && (__CYGWIN__ == 1)
  56. # define ELPP_CYGWIN 1
  57. #endif // defined(__CYGWIN__) && (__CYGWIN__ == 1)
  58. // Intel C++
  59. #if defined(__INTEL_COMPILER)
  60. # define ELPP_COMPILER_INTEL 1
  61. #endif
  62. // Operating System Evaluation
  63. // Windows
  64. #if defined(_WIN32) || defined(_WIN64)
  65. # define ELPP_OS_WINDOWS 1
  66. #endif // defined(_WIN32) || defined(_WIN64)
  67. // Linux
  68. #if (defined(__linux) || defined(__linux__))
  69. # define ELPP_OS_LINUX 1
  70. #endif // (defined(__linux) || defined(__linux__))
  71. // Mac
  72. #if defined(__APPLE__)
  73. # define ELPP_OS_MAC 1
  74. #endif // defined(__APPLE__)
  75. // FreeBSD
  76. #if defined(__FreeBSD__)
  77. # define ELPP_OS_FREEBSD 1
  78. #endif
  79. // Solaris
  80. #if defined(__sun)
  81. # define ELPP_OS_SOLARIS 1
  82. #endif
  83. // Unix
  84. #if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS))
  85. # define ELPP_OS_UNIX 1
  86. #endif // ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS))
  87. // Android
  88. #if defined(__ANDROID__)
  89. # define ELPP_OS_ANDROID 1
  90. #endif // defined(__ANDROID__)
  91. // Evaluating Cygwin as *nix OS
  92. #if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN
  93. # undef ELPP_OS_UNIX
  94. # undef ELPP_OS_LINUX
  95. # define ELPP_OS_UNIX 1
  96. # define ELPP_OS_LINUX 1
  97. #endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN
  98. #if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO)
  99. # define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout
  100. #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT)
  101. #if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR)
  102. # define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr
  103. #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT)
  104. #if !defined(ELPP_INTERNAL_DEBUGGING_ENDL)
  105. # define ELPP_INTERNAL_DEBUGGING_ENDL std::endl
  106. #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT)
  107. #if !defined(ELPP_INTERNAL_DEBUGGING_MSG)
  108. # define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg
  109. #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT)
  110. // Internal Assertions and errors
  111. #if !defined(ELPP_DISABLE_ASSERT)
  112. # if (defined(ELPP_DEBUG_ASSERT_FAILURE))
  113. # define ELPP_ASSERT(expr, msg) if (!(expr)) { \
  114. std::stringstream internalInfoStream; internalInfoStream << msg; \
  115. ELPP_INTERNAL_DEBUGGING_OUT_ERROR \
  116. << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \
  117. << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \
  118. "ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); }
  119. # else
  120. # define ELPP_ASSERT(expr, msg) if (!(expr)) { \
  121. std::stringstream internalInfoStream; internalInfoStream << msg; \
  122. ELPP_INTERNAL_DEBUGGING_OUT_ERROR\
  123. << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \
  124. << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \
  125. << ELPP_INTERNAL_DEBUGGING_ENDL; }
  126. # endif // (defined(ELPP_DEBUG_ASSERT_FAILURE))
  127. #else
  128. # define ELPP_ASSERT(x, y)
  129. #endif //(!defined(ELPP_DISABLE_ASSERT)
  130. #if ELPP_COMPILER_MSVC
  131. # define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \
  132. { char buff[256]; strerror_s(buff, 256, errno); \
  133. ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0
  134. #else
  135. # define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \
  136. ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0
  137. #endif // ELPP_COMPILER_MSVC
  138. #if defined(ELPP_DEBUG_ERRORS)
  139. # if !defined(ELPP_INTERNAL_ERROR)
  140. # define ELPP_INTERNAL_ERROR(msg, pe) { \
  141. std::stringstream internalInfoStream; internalInfoStream << "<ERROR> " << msg; \
  142. ELPP_INTERNAL_DEBUGGING_OUT_ERROR \
  143. << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \
  144. << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \
  145. if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0
  146. # endif
  147. #else
  148. # undef ELPP_INTERNAL_INFO
  149. # define ELPP_INTERNAL_ERROR(msg, pe)
  150. #endif // defined(ELPP_DEBUG_ERRORS)
  151. #if (defined(ELPP_DEBUG_INFO))
  152. # if !(defined(ELPP_INTERNAL_INFO_LEVEL))
  153. # define ELPP_INTERNAL_INFO_LEVEL 9
  154. # endif // !(defined(ELPP_INTERNAL_INFO_LEVEL))
  155. # if !defined(ELPP_INTERNAL_INFO)
  156. # define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \
  157. std::stringstream internalInfoStream; internalInfoStream << "<INFO> " << msg; \
  158. ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \
  159. << ELPP_INTERNAL_DEBUGGING_ENDL; }}
  160. # endif
  161. #else
  162. # undef ELPP_INTERNAL_INFO
  163. # define ELPP_INTERNAL_INFO(lvl, msg)
  164. #endif // (defined(ELPP_DEBUG_INFO))
  165. #if defined(ELPP_STACKTRACE_ON_CRASH)
  166. # if (ELPP_COMPILER_GCC && !ELPP_MINGW)
  167. # define ELPP_STACKTRACE 1
  168. # else
  169. # if ELPP_COMPILER_MSVC
  170. # pragma message("Stack trace not available for this compiler")
  171. # else
  172. # warning "Stack trace not available for this compiler";
  173. # endif // ELPP_COMPILER_MSVC
  174. # endif // ELPP_COMPILER_GCC
  175. #endif // (defined(ELPP_STACKTRACE_ON_CRASH))
  176. // Miscellaneous macros
  177. #define ELPP_UNUSED(x) (void)x
  178. #if ELPP_OS_UNIX
  179. // Log file permissions for unix-based systems
  180. # define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH
  181. #endif // ELPP_OS_UNIX
  182. #if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC
  183. # if defined(ELPP_EXPORT_SYMBOLS)
  184. # define ELPP_EXPORT __declspec(dllexport)
  185. # else
  186. # define ELPP_EXPORT __declspec(dllimport)
  187. # endif // defined(ELPP_EXPORT_SYMBOLS)
  188. #else
  189. # define ELPP_EXPORT
  190. #endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC
  191. // Some special functions that are VC++ specific
  192. #undef STRTOK
  193. #undef STRERROR
  194. #undef STRCAT
  195. #undef STRCPY
  196. #if ELPP_CRT_DBG_WARNINGS
  197. # define STRTOK(a, b, c) strtok_s(a, b, c)
  198. # define STRERROR(a, b, c) strerror_s(a, b, c)
  199. # define STRCAT(a, b, len) strcat_s(a, len, b)
  200. # define STRCPY(a, b, len) strcpy_s(a, len, b)
  201. #else
  202. # define STRTOK(a, b, c) strtok(a, b)
  203. # define STRERROR(a, b, c) strerror(c)
  204. # define STRCAT(a, b, len) strcat(a, b)
  205. # define STRCPY(a, b, len) strcpy(a, b)
  206. #endif
  207. // Compiler specific support evaluations
  208. #if (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD)
  209. # define ELPP_USE_STD_THREADING 1
  210. #endif // (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD)
  211. #undef ELPP_FINAL
  212. #if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702)
  213. # define ELPP_FINAL
  214. #else
  215. # define ELPP_FINAL final
  216. #endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702)
  217. #if defined(ELPP_EXPERIMENTAL_ASYNC)
  218. # define ELPP_ASYNC_LOGGING 1
  219. #else
  220. # define ELPP_ASYNC_LOGGING 0
  221. #endif // defined(ELPP_EXPERIMENTAL_ASYNC)
  222. #if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING
  223. # define ELPP_THREADING_ENABLED 1
  224. #endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING
  225. // Function macro ELPP_FUNC
  226. #undef ELPP_FUNC
  227. #if ELPP_COMPILER_MSVC // Visual C++
  228. # define ELPP_FUNC __FUNCSIG__
  229. #elif ELPP_COMPILER_GCC // GCC
  230. # define ELPP_FUNC __PRETTY_FUNCTION__
  231. #elif ELPP_COMPILER_INTEL // Intel C++
  232. # define ELPP_FUNC __PRETTY_FUNCTION__
  233. #elif ELPP_COMPILER_CLANG // Clang++
  234. # define ELPP_FUNC __PRETTY_FUNCTION__
  235. #else
  236. # if defined(__func__)
  237. # define ELPP_FUNC __func__
  238. # else
  239. # define ELPP_FUNC ""
  240. # endif // defined(__func__)
  241. #endif // defined(_MSC_VER)
  242. #undef ELPP_VARIADIC_TEMPLATES_SUPPORTED
  243. // Keep following line commented until features are fixed
  244. #if ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)
  245. # define ELPP_VARIADIC_TEMPLATES_SUPPORTED 1
  246. #endif // ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)
  247. // Logging Enable/Disable macros
  248. #if (!defined(ELPP_DISABLE_LOGS))
  249. # define ELPP_LOGGING_ENABLED 1
  250. #endif // (!defined(ELPP_DISABLE_LOGS))
  251. #if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG))))
  252. # define ELPP_DEBUG_LOG 1
  253. #else
  254. # define ELPP_DEBUG_LOG 0
  255. #endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG))))
  256. #if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED))
  257. # define ELPP_INFO_LOG 1
  258. #else
  259. # define ELPP_INFO_LOG 0
  260. #endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED))
  261. #if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED))
  262. # define ELPP_WARNING_LOG 1
  263. #else
  264. # define ELPP_WARNING_LOG 0
  265. #endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED))
  266. #if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED))
  267. # define ELPP_ERROR_LOG 1
  268. #else
  269. # define ELPP_ERROR_LOG 0
  270. #endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED))
  271. #if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED))
  272. # define ELPP_FATAL_LOG 1
  273. #else
  274. # define ELPP_FATAL_LOG 0
  275. #endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED))
  276. #if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED))
  277. # define ELPP_TRACE_LOG 1
  278. #else
  279. # define ELPP_TRACE_LOG 0
  280. #endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED))
  281. #if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED))
  282. # define ELPP_VERBOSE_LOG 1
  283. #else
  284. # define ELPP_VERBOSE_LOG 0
  285. #endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED))
  286. #if (!(ELPP_CXX0X || ELPP_CXX11))
  287. # error "Easylogging++ 9.0+ is only compatible with C++0x (or higher) compliant compiler"
  288. #endif // (!(ELPP_CXX0X || ELPP_CXX11))
  289. // Headers
  290. #if defined(ELPP_SYSLOG)
  291. # include <syslog.h>
  292. #endif // defined(ELPP_SYSLOG)
  293. #include <ctime>
  294. #include <cstring>
  295. #include <cstdlib>
  296. #include <cctype>
  297. #include <cwchar>
  298. #include <csignal>
  299. #include <cerrno>
  300. #include <cstdarg>
  301. #if defined(ELPP_UNICODE)
  302. # include <locale>
  303. # if ELPP_OS_WINDOWS
  304. # include <codecvt>
  305. # endif // ELPP_OS_WINDOWS
  306. #endif // defined(ELPP_UNICODE)
  307. #if ELPP_STACKTRACE
  308. # include <cxxabi.h>
  309. # include <execinfo.h>
  310. #endif // ELPP_STACKTRACE
  311. #if ELPP_OS_ANDROID
  312. # include <sys/system_properties.h>
  313. #endif // ELPP_OS_ANDROID
  314. #if ELPP_OS_UNIX
  315. # include <sys/stat.h>
  316. # include <sys/time.h>
  317. #elif ELPP_OS_WINDOWS
  318. # include <direct.h>
  319. # include <windows.h>
  320. # if defined(WIN32_LEAN_AND_MEAN)
  321. # if defined(ELPP_WINSOCK2)
  322. # include <winsock2.h>
  323. # else
  324. # include <winsock.h>
  325. # endif // defined(ELPP_WINSOCK2)
  326. # endif // defined(WIN32_LEAN_AND_MEAN)
  327. #endif // ELPP_OS_UNIX
  328. #include <string>
  329. #include <vector>
  330. #include <map>
  331. #include <utility>
  332. #include <functional>
  333. #include <algorithm>
  334. #include <fstream>
  335. #include <iostream>
  336. #include <sstream>
  337. #include <memory>
  338. #include <type_traits>
  339. #if ELPP_THREADING_ENABLED
  340. # if ELPP_USE_STD_THREADING
  341. # include <mutex>
  342. # include <thread>
  343. # else
  344. # if ELPP_OS_UNIX
  345. # include <pthread.h>
  346. # endif // ELPP_OS_UNIX
  347. # endif // ELPP_USE_STD_THREADING
  348. #endif // ELPP_THREADING_ENABLED
  349. #if ELPP_ASYNC_LOGGING
  350. # include <thread>
  351. # include <queue>
  352. # include <condition_variable>
  353. #endif // ELPP_ASYNC_LOGGING
  354. #if defined(ELPP_STL_LOGGING)
  355. // For logging STL based templates
  356. # include <list>
  357. # include <queue>
  358. # include <deque>
  359. # include <set>
  360. # include <bitset>
  361. # include <stack>
  362. # if defined(ELPP_LOG_STD_ARRAY)
  363. # include <array>
  364. # endif // defined(ELPP_LOG_STD_ARRAY)
  365. # if defined(ELPP_LOG_UNORDERED_MAP)
  366. # include <unordered_map>
  367. # endif // defined(ELPP_LOG_UNORDERED_MAP)
  368. # if defined(ELPP_LOG_UNORDERED_SET)
  369. # include <unordered_set>
  370. # endif // defined(ELPP_UNORDERED_SET)
  371. #endif // defined(ELPP_STL_LOGGING)
  372. #if defined(ELPP_QT_LOGGING)
  373. // For logging Qt based classes & templates
  374. # include <QString>
  375. # include <QByteArray>
  376. # include <QVector>
  377. # include <QList>
  378. # include <QPair>
  379. # include <QMap>
  380. # include <QQueue>
  381. # include <QSet>
  382. # include <QLinkedList>
  383. # include <QHash>
  384. # include <QMultiHash>
  385. # include <QStack>
  386. #endif // defined(ELPP_QT_LOGGING)
  387. #if defined(ELPP_BOOST_LOGGING)
  388. // For logging boost based classes & templates
  389. # include <boost/container/vector.hpp>
  390. # include <boost/container/stable_vector.hpp>
  391. # include <boost/container/list.hpp>
  392. # include <boost/container/deque.hpp>
  393. # include <boost/container/map.hpp>
  394. # include <boost/container/flat_map.hpp>
  395. # include <boost/container/set.hpp>
  396. # include <boost/container/flat_set.hpp>
  397. #endif // defined(ELPP_BOOST_LOGGING)
  398. #if defined(ELPP_WXWIDGETS_LOGGING)
  399. // For logging wxWidgets based classes & templates
  400. # include <wx/vector.h>
  401. #endif // defined(ELPP_WXWIDGETS_LOGGING)
  402. // Forward declarations
  403. namespace el {
  404. class Logger;
  405. class LogMessage;
  406. class PerformanceTrackingData;
  407. class Loggers;
  408. class Helpers;
  409. template <typename T> class Callback;
  410. class LogDispatchCallback;
  411. class PerformanceTrackingCallback;
  412. class LogDispatchData;
  413. namespace base {
  414. class Storage;
  415. class RegisteredLoggers;
  416. class PerformanceTracker;
  417. class MessageBuilder;
  418. class Writer;
  419. class PErrorWriter;
  420. class LogDispatcher;
  421. class DefaultLogBuilder;
  422. class DefaultLogDispatchCallback;
  423. #if ELPP_ASYNC_LOGGING
  424. class AsyncLogDispatchCallback;
  425. class AsyncDispatchWorker;
  426. #endif // ELPP_ASYNC_LOGGING
  427. class DefaultPerformanceTrackingCallback;
  428. } // namespace base
  429. } // namespace el
  430. /// @brief Easylogging++ entry namespace
  431. namespace el {
  432. /// @brief Namespace containing base/internal functionality used by Easylogging++
  433. namespace base {
  434. /// @brief Data types used by Easylogging++
  435. namespace type {
  436. #undef ELPP_LITERAL
  437. #undef ELPP_STRLEN
  438. #undef ELPP_COUT
  439. #if defined(ELPP_UNICODE)
  440. # define ELPP_LITERAL(txt) L##txt
  441. # define ELPP_STRLEN wcslen
  442. # if defined ELPP_CUSTOM_COUT
  443. # define ELPP_COUT ELPP_CUSTOM_COUT
  444. # else
  445. # define ELPP_COUT std::wcout
  446. # endif // defined ELPP_CUSTOM_COUT
  447. typedef wchar_t char_t;
  448. typedef std::wstring string_t;
  449. typedef std::wstringstream stringstream_t;
  450. typedef std::wfstream fstream_t;
  451. typedef std::wostream ostream_t;
  452. #else
  453. # define ELPP_LITERAL(txt) txt
  454. # define ELPP_STRLEN strlen
  455. # if defined ELPP_CUSTOM_COUT
  456. # define ELPP_COUT ELPP_CUSTOM_COUT
  457. # else
  458. # define ELPP_COUT std::cout
  459. # endif // defined ELPP_CUSTOM_COUT
  460. typedef char char_t;
  461. typedef std::string string_t;
  462. typedef std::stringstream stringstream_t;
  463. typedef std::fstream fstream_t;
  464. typedef std::ostream ostream_t;
  465. #endif // defined(ELPP_UNICODE)
  466. #if defined(ELPP_CUSTOM_COUT_LINE)
  467. # define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine)
  468. #else
  469. # define ELPP_COUT_LINE(logLine) logLine << std::flush
  470. #endif // defined(ELPP_CUSTOM_COUT_LINE)
  471. typedef unsigned short EnumType;
  472. typedef std::shared_ptr<base::Storage> StoragePointer;
  473. typedef int VerboseLevel;
  474. typedef std::shared_ptr<LogDispatchCallback> LogDispatchCallbackPtr;
  475. typedef std::shared_ptr<PerformanceTrackingCallback> PerformanceTrackingCallbackPtr;
  476. } // namespace type
  477. /// @brief Internal helper class that prevent copy constructor for class
  478. ///
  479. /// @detail When using this class simply inherit it privately
  480. class NoCopy
  481. {
  482. protected:
  483. NoCopy(void)
  484. {
  485. }
  486. private:
  487. NoCopy(const NoCopy&);
  488. NoCopy& operator=(const NoCopy&);
  489. };
  490. /// @brief Internal helper class that makes all default constructors private.
  491. ///
  492. /// @detail This prevents initializing class making it static unless an explicit constructor is declared.
  493. /// When using this class simply inherit it privately
  494. class StaticClass
  495. {
  496. private:
  497. StaticClass(void);
  498. StaticClass(const StaticClass&);
  499. StaticClass& operator=(const StaticClass&);
  500. };
  501. } // namespace base
  502. /// @brief Represents enumeration for severity level used to determine level of logging
  503. ///
  504. /// @detail With Easylogging++, developers may disable or enable any level regardless of
  505. /// what the severity is. Or they can choose to log using hierarchical logging flag
  506. enum class Level : base::type::EnumType
  507. {
  508. /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels
  509. Global = 1,
  510. /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs.
  511. Trace = 2,
  512. /// @brief Informational events most useful for developers to debug application
  513. Debug = 4,
  514. /// @brief Severe error information that will presumably abort application
  515. Fatal = 8,
  516. /// @brief Information representing errors in application but application will keep running
  517. Error = 16,
  518. /// @brief Useful when application has potentially harmful situtaions
  519. Warning = 32,
  520. /// @brief Information that can be highly useful and vary with verbose logging level.
  521. Verbose = 64,
  522. /// @brief Mainly useful to represent current progress of application
  523. Info = 128,
  524. /// @brief Represents unknown level
  525. Unknown = 1010
  526. };
  527. /// @brief Static class that contains helper functions for el::Level
  528. class LevelHelper : base::StaticClass
  529. {
  530. public:
  531. /// @brief Represents minimum valid level. Useful when iterating through enum.
  532. static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(Level::Trace);
  533. /// @brief Represents maximum valid level. This is used internally and you should not need it.
  534. static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(Level::Info);
  535. /// @brief Casts level to int, useful for iterating through enum.
  536. static base::type::EnumType castToInt(Level level)
  537. {
  538. return static_cast<base::type::EnumType>(level);
  539. }
  540. /// @brief Casts int(ushort) to level, useful for iterating through enum.
  541. static Level castFromInt(base::type::EnumType l)
  542. {
  543. return static_cast<Level>(l);
  544. }
  545. /// @brief Converts level to associated const char*
  546. /// @return Upper case string based level.
  547. static const char* convertToString(Level level)
  548. {
  549. // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet.
  550. if(level == Level::Global) return "GLOBAL";
  551. if(level == Level::Debug) return "DEBUG";
  552. if(level == Level::Info) return "INFO";
  553. if(level == Level::Warning) return "WARNING";
  554. if(level == Level::Error) return "ERROR";
  555. if(level == Level::Fatal) return "FATAL";
  556. if(level == Level::Verbose) return "VERBOSE";
  557. if(level == Level::Trace) return "TRACE";
  558. return "UNKNOWN";
  559. }
  560. /// @brief Converts from levelStr to Level
  561. /// @param levelStr Upper case string based level.
  562. /// Lower case is also valid but providing upper case is recommended.
  563. static Level convertFromString(const char* levelStr)
  564. {
  565. if((strcmp(levelStr, "GLOBAL") == 0) || (strcmp(levelStr, "global") == 0))
  566. return Level::Global;
  567. if((strcmp(levelStr, "DEBUG") == 0) || (strcmp(levelStr, "debug") == 0))
  568. return Level::Debug;
  569. if((strcmp(levelStr, "INFO") == 0) || (strcmp(levelStr, "info") == 0))
  570. return Level::Info;
  571. if((strcmp(levelStr, "WARNING") == 0) || (strcmp(levelStr, "warning") == 0))
  572. return Level::Warning;
  573. if((strcmp(levelStr, "ERROR") == 0) || (strcmp(levelStr, "error") == 0))
  574. return Level::Error;
  575. if((strcmp(levelStr, "FATAL") == 0) || (strcmp(levelStr, "fatal") == 0))
  576. return Level::Fatal;
  577. if((strcmp(levelStr, "VERBOSE") == 0) || (strcmp(levelStr, "verbose") == 0))
  578. return Level::Verbose;
  579. if((strcmp(levelStr, "TRACE") == 0) || (strcmp(levelStr, "trace") == 0))
  580. return Level::Trace;
  581. return Level::Unknown;
  582. }
  583. /// @brief Applies specified function to each level starting from startIndex
  584. /// @param startIndex initial value to start the iteration from. This is passed as pointer and
  585. /// is left-shifted so this can be used inside function (fn) to represent current level.
  586. /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels.
  587. static inline void forEachLevel(base::type::EnumType* startIndex, const std::function<bool(void)>& fn)
  588. {
  589. base::type::EnumType lIndexMax = LevelHelper::kMaxValid;
  590. do
  591. {
  592. if(fn())
  593. {
  594. break;
  595. }
  596. *startIndex = static_cast<base::type::EnumType>(*startIndex << 1);
  597. } while(*startIndex <= lIndexMax);
  598. }
  599. };
  600. /// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect
  601. /// of logging
  602. enum class ConfigurationType : base::type::EnumType
  603. {
  604. /// @brief Determines whether or not corresponding level and logger of logging is enabled
  605. /// You may disable all logs by using el::Level::Global
  606. Enabled = 1,
  607. /// @brief Whether or not to write corresponding log to log file
  608. ToFile = 2,
  609. /// @brief Whether or not to write corresponding level and logger log to standard output.
  610. /// By standard output meaning termnal, command prompt etc
  611. ToStandardOutput = 4,
  612. /// @brief Determines format of logging corresponding level and logger.
  613. Format = 8,
  614. /// @brief Determines log file (full path) to write logs to for correponding level and logger
  615. Filename = 16,
  616. /// @brief Specifies milliseconds width. Width can be within range (1-6)
  617. MillisecondsWidth = 32,
  618. /// @brief Determines whether or not performance tracking is enabled.
  619. ///
  620. /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger
  621. PerformanceTracking = 64,
  622. /// @brief Specifies log file max size.
  623. ///
  624. /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will
  625. /// be truncated and re-initiated.
  626. MaxLogFileSize = 128,
  627. /// @brief Specifies number of log entries to hold until we flush pending log data
  628. LogFlushThreshold = 256,
  629. /// @brief Represents unknown configuration
  630. Unknown = 1010
  631. };
  632. /// @brief Static class that contains helper functions for el::ConfigurationType
  633. class ConfigurationTypeHelper : base::StaticClass
  634. {
  635. public:
  636. /// @brief Represents minimum valid configuration type. Useful when iterating through enum.
  637. static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(ConfigurationType::Enabled);
  638. /// @brief Represents maximum valid configuration type. This is used internally and you should not need it.
  639. static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(ConfigurationType::MaxLogFileSize);
  640. /// @brief Casts configuration type to int, useful for iterating through enum.
  641. static base::type::EnumType castToInt(ConfigurationType configurationType)
  642. {
  643. return static_cast<base::type::EnumType>(configurationType);
  644. }
  645. /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum.
  646. static ConfigurationType castFromInt(base::type::EnumType c)
  647. {
  648. return static_cast<ConfigurationType>(c);
  649. }
  650. /// @brief Converts configuration type to associated const char*
  651. /// @returns Upper case string based configuration type.
  652. static const char* convertToString(ConfigurationType configurationType)
  653. {
  654. // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet.
  655. if(configurationType == ConfigurationType::Enabled) return "ENABLED";
  656. if(configurationType == ConfigurationType::Filename) return "FILENAME";
  657. if(configurationType == ConfigurationType::Format) return "FORMAT";
  658. if(configurationType == ConfigurationType::ToFile) return "TO_FILE";
  659. if(configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT";
  660. if(configurationType == ConfigurationType::MillisecondsWidth) return "MILLISECONDS_WIDTH";
  661. if(configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING";
  662. if(configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE";
  663. if(configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD";
  664. return "UNKNOWN";
  665. }
  666. /// @brief Converts from configStr to ConfigurationType
  667. /// @param configStr Upper case string based configuration type.
  668. /// Lower case is also valid but providing upper case is recommended.
  669. static ConfigurationType convertFromString(const char* configStr)
  670. {
  671. if((strcmp(configStr, "ENABLED") == 0) || (strcmp(configStr, "enabled") == 0))
  672. return ConfigurationType::Enabled;
  673. if((strcmp(configStr, "TO_FILE") == 0) || (strcmp(configStr, "to_file") == 0))
  674. return ConfigurationType::ToFile;
  675. if((strcmp(configStr, "TO_STANDARD_OUTPUT") == 0) || (strcmp(configStr, "to_standard_output") == 0))
  676. return ConfigurationType::ToStandardOutput;
  677. if((strcmp(configStr, "FORMAT") == 0) || (strcmp(configStr, "format") == 0))
  678. return ConfigurationType::Format;
  679. if((strcmp(configStr, "FILENAME") == 0) || (strcmp(configStr, "filename") == 0))
  680. return ConfigurationType::Filename;
  681. if((strcmp(configStr, "MILLISECONDS_WIDTH") == 0) || (strcmp(configStr, "milliseconds_width") == 0))
  682. return ConfigurationType::MillisecondsWidth;
  683. if((strcmp(configStr, "PERFORMANCE_TRACKING") == 0) || (strcmp(configStr, "performance_tracking") == 0))
  684. return ConfigurationType::PerformanceTracking;
  685. if((strcmp(configStr, "MAX_LOG_FILE_SIZE") == 0) || (strcmp(configStr, "max_log_file_size") == 0))
  686. return ConfigurationType::MaxLogFileSize;
  687. if((strcmp(configStr, "LOG_FLUSH_THRESHOLD") == 0) || (strcmp(configStr, "log_flush_threshold") == 0))
  688. return ConfigurationType::LogFlushThreshold;
  689. return ConfigurationType::Unknown;
  690. }
  691. /// @brief Applies specified function to each configuration type starting from startIndex
  692. /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted
  693. /// so this can be used inside function (fn) to represent current configuration type.
  694. /// @param fn function to apply with each configuration type.
  695. /// This bool represent whether or not to stop iterating through configurations.
  696. static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function<bool(void)>& fn)
  697. {
  698. base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid;
  699. do
  700. {
  701. if(fn())
  702. {
  703. break;
  704. }
  705. *startIndex = static_cast<base::type::EnumType>(*startIndex << 1);
  706. } while(*startIndex <= cIndexMax);
  707. }
  708. };
  709. /// @brief Flags used while writing logs. This flags are set by user
  710. enum class LoggingFlag : base::type::EnumType
  711. {
  712. /// @brief Makes sure we have new line for each container log entry
  713. NewLineForContainer = 1,
  714. /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose
  715. /// logging is allowed via that module.
  716. AllowVerboseIfModuleNotSpecified = 2,
  717. /// @brief When handling crashes by default, detailed crash reason will be logged as well
  718. LogDetailedCrashReason = 4,
  719. /// @brief Allows to disable application abortion when logged using FATAL level
  720. DisableApplicationAbortOnFatalLog = 8,
  721. /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default
  722. ImmediateFlush = 16,
  723. /// @brief Enables strict file rolling
  724. StrictLogFileSizeCheck = 32,
  725. /// @brief Make terminal output colorful for supported terminals
  726. ColoredTerminalOutput = 64,
  727. /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network")
  728. MultiLoggerSupport = 128,
  729. /// @brief Disables comparing performance tracker's checkpoints
  730. DisablePerformanceTrackingCheckpointComparison = 256,
  731. /// @brief Disable VModules
  732. DisableVModules = 512,
  733. /// @brief Disable VModules extensions
  734. DisableVModulesExtensions = 1024,
  735. /// @brief Enables hierarchical logging
  736. HierarchicalLogging = 2048,
  737. /// @brief Creates logger automatically when not available
  738. CreateLoggerAutomatically = 4096,
  739. /// @brief Adds spaces b/w logs that separated by left-shift operator
  740. AutoSpacing = 8192,
  741. /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only)
  742. FixedTimeFormat = 16384
  743. };
  744. namespace base {
  745. /// @brief Namespace containing constants used internally.
  746. namespace consts {
  747. // Level log values - These are values that are replaced in place of %level format specifier
  748. static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO ");
  749. static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG");
  750. static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARN ");
  751. static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR");
  752. static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL");
  753. static const base::type::char_t* kVerboseLevelLogValue = ELPP_LITERAL("VER");
  754. static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE");
  755. static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I");
  756. static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D");
  757. static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W");
  758. static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E");
  759. static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F");
  760. static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V");
  761. static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T");
  762. // Format specifiers - These are used to define log format
  763. static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app");
  764. static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger");
  765. static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread");
  766. static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level");
  767. static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort");
  768. static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime");
  769. static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file");
  770. static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase");
  771. static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line");
  772. static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc");
  773. static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func");
  774. static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user");
  775. static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host");
  776. static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg");
  777. static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel");
  778. static const char* kDateTimeFormatSpecifierForFilename = "%datetime";
  779. // Date/time
  780. static const char* kDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
  781. static const char* kDaysAbbrev[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  782. static const char* kMonths[12] = {"January", "February", "March", "Apri", "May", "June", "July", "August",
  783. "September", "October", "November", "December"};
  784. static const char* kMonthsAbbrev[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  785. static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g";
  786. static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m";
  787. static const int kYearBase = 1900;
  788. static const char* kAm = "AM";
  789. static const char* kPm = "PM";
  790. // Miscellaneous constants
  791. static const char* kDefaultLoggerId = "default";
  792. static const char* kPerformanceLoggerId = "performance";
  793. static const char* kSysLogLoggerId = "syslog";
  794. static const char* kNullPointer = "nullptr";
  795. static const char kFormatSpecifierChar = '%';
  796. #if ELPP_VARIADIC_TEMPLATES_SUPPORTED
  797. static const char kFormatSpecifierCharValue = 'v';
  798. #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED
  799. static const unsigned int kMaxLogPerContainer = 100;
  800. static const unsigned int kMaxLogPerCounter = 100000;
  801. static const unsigned int kDefaultMillisecondsWidth = 3;
  802. static const base::type::VerboseLevel kMaxVerboseLevel = 9;
  803. static const char* kUnknownUser = "user";
  804. static const char* kUnknownHost = "unknown-host";
  805. #if defined(ELPP_DEFAULT_LOG_FILE)
  806. static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE;
  807. #else
  808. # if ELPP_OS_UNIX
  809. # if ELPP_OS_ANDROID
  810. static const char* kDefaultLogFile = "logs/myeasylog.log";
  811. # else
  812. static const char* kDefaultLogFile = "logs/myeasylog.log";
  813. # endif // ELPP_OS_ANDROID
  814. # elif ELPP_OS_WINDOWS
  815. static const char* kDefaultLogFile = "logs/myeasylog.log";
  816. # endif // ELPP_OS_UNIX
  817. #endif // defined(ELPP_DEFAULT_LOG_FILE)
  818. #if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
  819. static const char* kDefaultLogFileParam = "--default-log-file";
  820. #endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
  821. #if defined(ELPP_LOGGING_FLAGS_FROM_ARG)
  822. static const char* kLoggingFlagsParam = "--logging-flags";
  823. #endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG)
  824. #if ELPP_OS_WINDOWS
  825. static const char* kFilePathSeperator = "\\";
  826. #else
  827. static const char* kFilePathSeperator = "/";
  828. #endif // ELPP_OS_WINDOWS
  829. static const char* kValidLoggerIdSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._";
  830. static const char* kConfigurationComment = "##";
  831. static const char* kConfigurationLevel = "*";
  832. static const char* kConfigurationLoggerId = "--";
  833. static const std::size_t kSourceFilenameMaxLength = 100;
  834. static const std::size_t kSourceLineMaxLength = 10;
  835. static const Level kPerformanceTrackerDefaultLevel = Level::Info;
  836. const struct
  837. {
  838. double value;
  839. const base::type::char_t* unit;
  840. } kTimeFormats[] = {
  841. {1000.0f, ELPP_LITERAL("mis")},
  842. {1000.0f, ELPP_LITERAL("ms")},
  843. {60.0f, ELPP_LITERAL("seconds")},
  844. {60.0f, ELPP_LITERAL("minutes")},
  845. {24.0f, ELPP_LITERAL("hours")},
  846. {7.0f, ELPP_LITERAL("days")}
  847. };
  848. static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]);
  849. const struct
  850. {
  851. int numb;
  852. const char* name;
  853. const char* brief;
  854. const char* detail;
  855. } kCrashSignals[] = {
  856. // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..)
  857. {SIGABRT, "SIGABRT", "Abnormal termination",
  858. "Program was abnormally terminated."},
  859. {SIGFPE, "SIGFPE", "Erroneous arithmetic operation",
  860. "Arithemetic operation issue such as division by zero or operation resulting in overflow."},
  861. {SIGILL, "SIGILL", "Illegal instruction",
  862. "Generally due to a corruption in the code or to an attempt to execute data."},
  863. {SIGSEGV, "SIGSEGV", "Invalid access to memory",
  864. "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory."},
  865. // { SIGINT, "SIGINT", "Interactive attention signal",
  866. // "Interruption generated (generally) by user or operating system." },
  867. };
  868. static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]);
  869. } // namespace consts
  870. } // namespace base
  871. typedef std::function<void(const char*, std::size_t)> PreRollOutCallback;
  872. namespace base {
  873. static inline void defaultPreRollOutCallback(const char*, std::size_t)
  874. {
  875. }
  876. /// @brief Enum to represent timestamp unit
  877. enum class TimestampUnit : base::type::EnumType
  878. {
  879. Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5
  880. };
  881. /// @brief Format flags used to determine specifiers that are active for performance improvements.
  882. enum class FormatFlags : base::type::EnumType
  883. {
  884. DateTime = 1 << 1, LoggerId = 1 << 2, File = 1 << 3, Line = 1 << 4, Location = 1 << 5, Function = 1 << 6,
  885. User = 1 << 7, Host = 1 << 8, LogMessage = 1 << 9, VerboseLevel = 1 << 10, AppName = 1 << 11, ThreadId = 1 << 12,
  886. Level = 1 << 13, FileBase = 1 << 14, LevelShort = 1 << 15
  887. };
  888. /// @brief A milliseconds width class containing actual width and offset for date/time
  889. class MillisecondsWidth
  890. {
  891. public:
  892. MillisecondsWidth(void)
  893. {
  894. init(base::consts::kDefaultMillisecondsWidth);
  895. }
  896. explicit MillisecondsWidth(int width)
  897. {
  898. init(width);
  899. }
  900. bool operator==(const MillisecondsWidth& msWidth)
  901. {
  902. return m_width == msWidth.m_width && m_offset == msWidth.m_offset;
  903. }
  904. int m_width; unsigned int m_offset;
  905. private:
  906. void init(int width)
  907. {
  908. if(width < 1 || width > 6)
  909. {
  910. width = base::consts::kDefaultMillisecondsWidth;
  911. }
  912. m_width = width;
  913. switch(m_width)
  914. {
  915. case 3: m_offset = 1000; break;
  916. case 4: m_offset = 100; break;
  917. case 5: m_offset = 10; break;
  918. case 6: m_offset = 1; break;
  919. default: m_offset = 1000; break;
  920. }
  921. }
  922. };
  923. /// @brief Namespace containing utility functions/static classes used internally
  924. namespace utils {
  925. /// @brief Deletes memory safely and points to null
  926. template <typename T>
  927. static inline
  928. typename std::enable_if<std::is_pointer<T*>::value, void>::type
  929. safeDelete(T*& pointer)
  930. {
  931. if(pointer == nullptr)
  932. return;
  933. delete pointer;
  934. pointer = nullptr;
  935. }
  936. /// @brief Gets value of const char* but if it is nullptr, a string nullptr is returned
  937. static inline const char* charPtrVal(const char* pointer)
  938. {
  939. return pointer == nullptr ? base::consts::kNullPointer : pointer;
  940. }
  941. /// @brief Aborts application due with user-defined status
  942. static inline void abort(int status, const std::string& reason = std::string())
  943. {
  944. // Both status and reason params are there for debugging with tools like gdb etc
  945. ELPP_UNUSED(status);
  946. ELPP_UNUSED(reason);
  947. #if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
  948. // Ignore msvc critical error dialog - break instead (on debug mode)
  949. _asm int 3
  950. #else
  951. ::abort();
  952. #endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
  953. }
  954. /// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation
  955. /// Use these function as <pre>flag = bitwise::Or<MyEnum>(MyEnum::val1, flag);</pre>
  956. namespace bitwise {
  957. template <typename Enum>
  958. static inline base::type::EnumType And(Enum e, base::type::EnumType flag)
  959. {
  960. return static_cast<base::type::EnumType>(flag) & static_cast<base::type::EnumType>(e);
  961. }
  962. template <typename Enum>
  963. static inline base::type::EnumType Not(Enum e, base::type::EnumType flag)
  964. {
  965. return static_cast<base::type::EnumType>(flag) & ~(static_cast<base::type::EnumType>(e));
  966. }
  967. template <typename Enum>
  968. static inline base::type::EnumType Or(Enum e, base::type::EnumType flag)
  969. {
  970. return static_cast<base::type::EnumType>(flag) | static_cast<base::type::EnumType>(e);
  971. }
  972. } // namespace bitwise
  973. template <typename Enum>
  974. static inline void addFlag(Enum e, base::type::EnumType* flag)
  975. {
  976. *flag = base::utils::bitwise::Or<Enum>(e, *flag);
  977. }
  978. template <typename Enum>
  979. static inline void removeFlag(Enum e, base::type::EnumType* flag)
  980. {
  981. *flag = base::utils::bitwise::Not<Enum>(e, *flag);
  982. }
  983. template <typename Enum>
  984. static inline bool hasFlag(Enum e, base::type::EnumType flag)
  985. {
  986. return base::utils::bitwise::And<Enum>(e, flag) > 0x0;
  987. }
  988. } // namespace utils
  989. namespace threading {
  990. #if ELPP_THREADING_ENABLED
  991. # if !ELPP_USE_STD_THREADING
  992. namespace internal {
  993. /// @brief A mutex wrapper for compiler that dont yet support std::mutex
  994. class Mutex : base::NoCopy
  995. {
  996. public:
  997. Mutex(void)
  998. {
  999. # if ELPP_OS_UNIX
  1000. pthread_mutex_init(&m_underlyingMutex, nullptr);
  1001. # elif ELPP_OS_WINDOWS
  1002. InitializeCriticalSection(&m_underlyingMutex);
  1003. # endif // ELPP_OS_UNIX
  1004. }
  1005. virtual ~Mutex(void)
  1006. {
  1007. # if ELPP_OS_UNIX
  1008. pthread_mutex_destroy(&m_underlyingMutex);
  1009. # elif ELPP_OS_WINDOWS
  1010. DeleteCriticalSection(&m_underlyingMutex);
  1011. # endif // ELPP_OS_UNIX
  1012. }
  1013. inline void lock(void)
  1014. {
  1015. # if ELPP_OS_UNIX
  1016. pthread_mutex_lock(&m_underlyingMutex);
  1017. # elif ELPP_OS_WINDOWS
  1018. EnterCriticalSection(&m_underlyingMutex);
  1019. # endif // ELPP_OS_UNIX
  1020. }
  1021. inline bool try_lock(void)
  1022. {
  1023. # if ELPP_OS_UNIX
  1024. return (pthread_mutex_trylock(&m_underlyingMutex) == 0);
  1025. # elif ELPP_OS_WINDOWS
  1026. return TryEnterCriticalSection(&m_underlyingMutex);
  1027. # endif // ELPP_OS_UNIX
  1028. }
  1029. inline void unlock(void)
  1030. {
  1031. # if ELPP_OS_UNIX
  1032. pthread_mutex_unlock(&m_underlyingMutex);
  1033. # elif ELPP_OS_WINDOWS
  1034. LeaveCriticalSection(&m_underlyingMutex);
  1035. # endif // ELPP_OS_UNIX
  1036. }
  1037. private:
  1038. # if ELPP_OS_UNIX
  1039. pthread_mutex_t m_underlyingMutex;
  1040. # elif ELPP_OS_WINDOWS
  1041. CRITICAL_SECTION m_underlyingMutex;
  1042. # endif // ELPP_OS_UNIX
  1043. };
  1044. /// @brief Scoped lock for compiler that dont yet support std::lock_guard
  1045. template <typename M>
  1046. class ScopedLock : base::NoCopy
  1047. {
  1048. public:
  1049. explicit ScopedLock(M& mutex)
  1050. {
  1051. m_mutex = &mutex;
  1052. m_mutex->lock();
  1053. }
  1054. virtual ~ScopedLock(void)
  1055. {
  1056. m_mutex->unlock();
  1057. }
  1058. private:
  1059. M* m_mutex;
  1060. ScopedLock(void);
  1061. };
  1062. } // namespace internal
  1063. /// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned.
  1064. static inline std::string getCurrentThreadId(void)
  1065. {
  1066. std::stringstream ss;
  1067. # if (ELPP_OS_WINDOWS)
  1068. ss << GetCurrentThreadId();
  1069. # endif // (ELPP_OS_WINDOWS)
  1070. return ss.str();
  1071. }
  1072. static inline void msleep(int)
  1073. {
  1074. // No implementation for non std::thread version
  1075. }
  1076. typedef base::threading::internal::Mutex Mutex;
  1077. typedef base::threading::internal::ScopedLock<base::threading::Mutex> ScopedLock;
  1078. # else
  1079. /// @brief Gets ID of currently running threading using std::this_thread::get_id()
  1080. static inline std::string getCurrentThreadId(void)
  1081. {
  1082. std::stringstream ss;
  1083. ss << std::this_thread::get_id();
  1084. return ss.str();
  1085. }
  1086. static inline void msleep(int ms)
  1087. {
  1088. // Only when async logging enabled - this is because async is strict on compiler
  1089. #if ELPP_ASYNC_LOGGING
  1090. std::this_thread::sleep_for(std::chrono::milliseconds(ms));
  1091. #endif // ELPP_ASYNC_LOGGING
  1092. }
  1093. typedef std::mutex Mutex;
  1094. typedef std::lock_guard<std::mutex> ScopedLock;
  1095. # endif // !ELPP_USE_STD_THREADING
  1096. #else
  1097. namespace internal {
  1098. /// @brief Mutex wrapper used when multi-threading is disabled.
  1099. class NoMutex : base::NoCopy
  1100. {
  1101. public:
  1102. NoMutex(void)
  1103. {
  1104. }
  1105. inline void lock(void)
  1106. {
  1107. }
  1108. inline bool try_lock(void)
  1109. {
  1110. return true;
  1111. }
  1112. inline void unlock(void)
  1113. {
  1114. }
  1115. };
  1116. /// @brief Lock guard wrapper used when multi-threading is disabled.
  1117. template <typename Mutex>
  1118. class NoScopedLock : base::NoCopy
  1119. {
  1120. public:
  1121. explicit NoScopedLock(Mutex&)
  1122. {
  1123. }
  1124. virtual ~NoScopedLock(void)
  1125. {
  1126. }
  1127. private:
  1128. NoScopedLock(void);
  1129. };
  1130. } // namespace internal
  1131. static inline std::string getCurrentThreadId(void)
  1132. {
  1133. return std::string();
  1134. }
  1135. static inline void msleep(int)
  1136. {
  1137. // No custom implementation
  1138. }
  1139. typedef base::threading::internal::NoMutex Mutex;
  1140. typedef base::threading::internal::NoScopedLock<base::threading::Mutex> ScopedLock;
  1141. #endif // ELPP_THREADING_ENABLED
  1142. /// @brief Base of thread safe class, this class is inheritable-only
  1143. class ThreadSafe
  1144. {
  1145. public:
  1146. virtual inline void acquireLock(void) ELPP_FINAL
  1147. {
  1148. m_mutex.lock();
  1149. }
  1150. virtual inline void releaseLock(void) ELPP_FINAL
  1151. {
  1152. m_mutex.unlock();
  1153. }
  1154. virtual inline base::threading::Mutex& lock(void) ELPP_FINAL
  1155. {
  1156. return m_mutex;
  1157. }
  1158. protected:
  1159. ThreadSafe(void)
  1160. {
  1161. }
  1162. virtual ~ThreadSafe(void)
  1163. {
  1164. }
  1165. private:
  1166. base::threading::Mutex m_mutex;
  1167. };
  1168. } // namespace threading
  1169. namespace utils {
  1170. class File : base::StaticClass
  1171. {
  1172. public:
  1173. /// @brief Creates new out file stream for specified filename.
  1174. /// @return Pointer to newly created fstream or nullptr
  1175. static base::type::fstream_t* newFileStream(const std::string& filename)
  1176. {
  1177. base::type::fstream_t* fs = new base::type::fstream_t(filename.c_str(),
  1178. base::type::fstream_t::out | base::type::fstream_t::app);
  1179. #if defined(ELPP_UNICODE)
  1180. std::locale elppUnicodeLocale("");
  1181. #if ELPP_OS_WINDOWS
  1182. std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16<wchar_t>);
  1183. elppUnicodeLocale = elppUnicodeLocaleWindows;
  1184. #endif
  1185. fs->imbue(elppUnicodeLocale);
  1186. #endif // defined(ELPP_UNICODE)
  1187. if(fs->is_open())
  1188. {
  1189. fs->flush();
  1190. }
  1191. else
  1192. {
  1193. base::utils::safeDelete(fs);
  1194. ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true);
  1195. }
  1196. return fs;
  1197. }
  1198. /// @brief Gets size of file provided in stream
  1199. static /*std::size_t*/int64_t getSizeOfFile(base::type::fstream_t* fs)
  1200. {
  1201. if(fs == nullptr)
  1202. {
  1203. return 0;
  1204. }
  1205. std::streampos currPos = fs->tellg();
  1206. fs->seekg(0, fs->end);
  1207. /*std::size_t*/int64_t size = static_cast</*std::size_t*/int64_t>(fs->tellg());
  1208. fs->seekg(currPos);
  1209. return size;
  1210. }
  1211. /// @brief Determines whether or not provided path exist in current file system
  1212. static inline bool pathExists(const char* path, bool considerFile = false)
  1213. {
  1214. if(path == nullptr)
  1215. {
  1216. return false;
  1217. }
  1218. #if ELPP_OS_UNIX
  1219. ELPP_UNUSED(considerFile);
  1220. struct stat st;
  1221. return (stat(path, &st) == 0);
  1222. #elif ELPP_OS_WINDOWS
  1223. DWORD fileType = GetFileAttributesA(path);
  1224. if(fileType == INVALID_FILE_ATTRIBUTES)
  1225. {
  1226. return false;
  1227. }
  1228. return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true);
  1229. #endif // ELPP_OS_UNIX
  1230. }
  1231. /// @brief Creates specified path on file system
  1232. /// @param path Path to create.
  1233. static bool createPath(const std::string& path)
  1234. {
  1235. if(path.empty())
  1236. {
  1237. return false;
  1238. }
  1239. if(base::utils::File::pathExists(path.c_str()))
  1240. {
  1241. return true;
  1242. }
  1243. int status = -1;
  1244. char* currPath = const_cast<char*>(path.c_str());
  1245. std::string builtPath = std::string();
  1246. #if ELPP_OS_UNIX
  1247. if(path[0] == '/')
  1248. {
  1249. builtPath = "/";
  1250. }
  1251. currPath = STRTOK(currPath, base::consts::kFilePathSeperator, 0);
  1252. #elif ELPP_OS_WINDOWS
  1253. // Use secure functions API
  1254. char* nextTok_ = nullptr;
  1255. currPath = STRTOK(currPath, base::consts::kFilePathSeperator, &nextTok_);
  1256. ELPP_UNUSED(nextTok_);
  1257. #endif // ELPP_OS_UNIX
  1258. while(currPath != nullptr)
  1259. {
  1260. builtPath.append(currPath);
  1261. builtPath.append(base::consts::kFilePathSeperator);
  1262. #if ELPP_OS_UNIX
  1263. status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS);
  1264. currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, 0);
  1265. #elif ELPP_OS_WINDOWS
  1266. status = _mkdir(builtPath.c_str());
  1267. currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, &nextTok_);
  1268. #endif // ELPP_OS_UNIX
  1269. }
  1270. if(status == -1)
  1271. {
  1272. ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true);
  1273. return false;
  1274. }
  1275. return true;
  1276. }
  1277. /// @brief Extracts path of filename with leading slash
  1278. static std::string extractPathFromFilename(const std::string& fullPath,
  1279. const char* seperator = base::consts::kFilePathSeperator)
  1280. {
  1281. if((fullPath == "") || (fullPath.find(seperator) == std::string::npos))
  1282. {
  1283. return fullPath;
  1284. }
  1285. std::size_t lastSlashAt = fullPath.find_last_of(seperator);
  1286. if(lastSlashAt == 0)
  1287. {
  1288. return std::string(seperator);
  1289. }
  1290. return fullPath.substr(0, lastSlashAt + 1);
  1291. }
  1292. /// @brief builds stripped filename and puts it in buff
  1293. static void buildStrippedFilename(const char* filename, char buff[],
  1294. std::size_t limit = base::consts::kSourceFilenameMaxLength)
  1295. {
  1296. std::size_t sizeOfFilename = strlen(filename);
  1297. if(sizeOfFilename >= limit)
  1298. {
  1299. filename += (sizeOfFilename - limit);
  1300. if(filename[0] != '.' && filename[1] != '.')
  1301. { // prepend if not already
  1302. filename += 3; // 3 = '..'
  1303. STRCAT(buff, "..", limit);
  1304. }
  1305. }
  1306. STRCAT(buff, filename, limit);
  1307. }
  1308. /// @brief builds base filename and puts it in buff
  1309. static void buildBaseFilename(const std::string& fullPath, char buff[],
  1310. std::size_t limit = base::consts::kSourceFilenameMaxLength,
  1311. const char* seperator = base::consts::kFilePathSeperator)
  1312. {
  1313. const char* filename = fullPath.c_str();
  1314. std::size_t lastSlashAt = fullPath.find_last_of(seperator);
  1315. filename += lastSlashAt ? lastSlashAt + 1 : 0;
  1316. std::size_t sizeOfFilename = strlen(filename);
  1317. if(sizeOfFilename >= limit)
  1318. {
  1319. filename += (sizeOfFilename - limit);
  1320. if(filename[0] != '.' && filename[1] != '.')
  1321. { // prepend if not already
  1322. filename += 3; // 3 = '..'
  1323. STRCAT(buff, "..", limit);
  1324. }
  1325. }
  1326. STRCAT(buff, filename, limit);
  1327. }
  1328. };
  1329. /// @brief String utilities helper class used internally. You should not use it.
  1330. class Str : base::StaticClass
  1331. {
  1332. public:
  1333. /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues.
  1334. static inline bool isDigit(char c)
  1335. {
  1336. return c >= '0' && c <= '9';
  1337. }
  1338. /// @brief Matches wildcards, '*' and '?' only supported.
  1339. static bool wildCardMatch(const char* str, const char* pattern)
  1340. {
  1341. while(*pattern)
  1342. {
  1343. switch(*pattern)
  1344. {
  1345. case '?':
  1346. if(!*str)
  1347. return false;
  1348. ++str;
  1349. ++pattern;
  1350. break;
  1351. case '*':
  1352. if(wildCardMatch(str, pattern + 1))
  1353. return true;
  1354. if(*str && wildCardMatch(str + 1, pattern))
  1355. return true;
  1356. return false;
  1357. break;
  1358. default:
  1359. if(*str++ != *pattern++)
  1360. return false;
  1361. break;
  1362. }
  1363. }
  1364. return !*str && !*pattern;
  1365. }
  1366. /// @brief Trims string from start
  1367. /// @param [in,out] str String to trim
  1368. static inline std::string& ltrim(std::string& str)
  1369. {
  1370. str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::not_fn(static_cast<int(*)(int)>(std::isspace))));
  1371. return str;
  1372. }
  1373. /// @brief Trim string from end
  1374. /// @param [in,out] str String to trim
  1375. static inline std::string& rtrim(std::string& str)
  1376. {
  1377. str.erase(std::find_if(str.rbegin(), str.rend(), std::not_fn(static_cast<int(*)(int)>(std::isspace))).base(), str.end());
  1378. return str;
  1379. }
  1380. /// @brief Trims string from left and right
  1381. /// @param [in,out] str String to trim
  1382. static inline std::string& trim(std::string& str)
  1383. {
  1384. return ltrim(rtrim(str));
  1385. }
  1386. /// @brief Determines whether or not str starts with specified string
  1387. /// @param str String to check
  1388. /// @param start String to check against
  1389. /// @return Returns true if starts with specified string, false otherwise
  1390. static inline bool startsWith(const std::string& str, const std::string& start)
  1391. {
  1392. return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0);
  1393. }
  1394. /// @brief Determines whether or not str ends with specified string
  1395. /// @param str String to check
  1396. /// @param end String to check against
  1397. /// @return Returns true if ends with specified string, false otherwise
  1398. static inline bool endsWith(const std::string& str, const std::string& end)
  1399. {
  1400. return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0);
  1401. }
  1402. /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance.
  1403. /// @param [in,out] str String to replace from
  1404. /// @param replaceWhat Character to replace
  1405. /// @param replaceWith Character to replace with
  1406. /// @return Modified version of str
  1407. static inline std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith)
  1408. {
  1409. std::replace(str.begin(), str.end(), replaceWhat, replaceWith);
  1410. return str;
  1411. }
  1412. /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place
  1413. /// @param str String to replace from
  1414. /// @param replaceWhat Character to replace
  1415. /// @param replaceWith Character to replace with
  1416. /// @return Modified (original) str
  1417. static inline std::string& replaceAll(std::string& str, const std::string& replaceWhat, // NOLINT
  1418. const std::string& replaceWith)
  1419. {
  1420. if(replaceWhat == replaceWith)
  1421. return str;
  1422. std::size_t foundAt = std::string::npos;
  1423. while((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos)
  1424. {
  1425. str.replace(foundAt, replaceWhat.length(), replaceWith);
  1426. }
  1427. return str;
  1428. }
  1429. static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT
  1430. const base::type::string_t& replaceWith)
  1431. {
  1432. std::size_t foundAt = base::type::string_t::npos;
  1433. while((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos)
  1434. {
  1435. if(foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar)
  1436. {
  1437. str.erase(foundAt > 0 ? foundAt - 1 : 0, 1);
  1438. ++foundAt;
  1439. }
  1440. else
  1441. {
  1442. str.replace(foundAt, replaceWhat.length(), replaceWith);
  1443. return;
  1444. }
  1445. }
  1446. }
  1447. #if defined(ELPP_UNICODE)
  1448. static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT
  1449. const std::string& replaceWith)
  1450. {
  1451. replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end()));
  1452. }
  1453. #endif // defined(ELPP_UNICODE)
  1454. /// @brief Converts string to uppercase
  1455. /// @param str String to convert
  1456. /// @return Uppercase string
  1457. static inline std::string& toUpper(std::string& str)
  1458. {
  1459. std::transform(str.begin(), str.end(), str.begin(), ::toupper);
  1460. return str;
  1461. }
  1462. /// @brief Compares cstring equality - uses strcmp
  1463. static inline bool cStringEq(const char* s1, const char* s2)
  1464. {
  1465. if(s1 == nullptr && s2 == nullptr) return true;
  1466. if(s1 == nullptr || s2 == nullptr) return false;
  1467. return strcmp(s1, s2) == 0;
  1468. }
  1469. /// @brief Compares cstring equality (case-insensitive) - uses toupper(char)
  1470. /// Dont use strcasecmp because of CRT (VC++)
  1471. static bool cStringCaseEq(const char* s1, const char* s2)
  1472. {
  1473. if(s1 == nullptr && s2 == nullptr) return true;
  1474. if(s1 == nullptr || s2 == nullptr) return false;
  1475. if(strlen(s1) != strlen(s2)) return false;
  1476. while(*s1 != '\0' && *s2 != '\0')
  1477. {
  1478. if(::toupper(*s1) != ::toupper(*s2)) return false;
  1479. ++s1;
  1480. ++s2;
  1481. }
  1482. return true;
  1483. }
  1484. /// @brief Returns true if c exist in str
  1485. static inline bool contains(const char* str, char c)
  1486. {
  1487. for(; *str; ++str)
  1488. {
  1489. if(*str == c)
  1490. return true;
  1491. }
  1492. return false;
  1493. }
  1494. static inline char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true)
  1495. {
  1496. char localBuff[10] = "";
  1497. char* p = localBuff + sizeof(localBuff) - 2;
  1498. if(n > 0)
  1499. {
  1500. for(; n > 0 && p > localBuff && len > 0; n /= 10, --len)
  1501. *--p = static_cast<char>(n % 10 + '0');
  1502. }
  1503. else
  1504. {
  1505. *--p = '0';
  1506. --len;
  1507. }
  1508. if(zeroPadded)
  1509. while(p > localBuff && len-- > 0) *--p = static_cast<char>('0');
  1510. return addToBuff(p, buf, bufLim);
  1511. }
  1512. static inline char* addToBuff(const char* str, char* buf, const char* bufLim)
  1513. {
  1514. while((buf < bufLim) && ((*buf = *str++) != '\0'))
  1515. ++buf;
  1516. return buf;
  1517. }
  1518. static inline char* clearBuff(char buff[], std::size_t lim)
  1519. {
  1520. STRCPY(buff, "", lim);
  1521. ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro
  1522. return buff;
  1523. }
  1524. /// @brief Converst wchar* to char*
  1525. /// NOTE: Need to free return value after use!
  1526. static char* wcharPtrToCharPtr(const wchar_t* line)
  1527. {
  1528. std::size_t len_ = wcslen(line) + 1;
  1529. char* buff_ = static_cast<char*>(malloc(len_ + 1));
  1530. # if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS)
  1531. std::wcstombs(buff_, line, len_);
  1532. # elif ELPP_OS_WINDOWS
  1533. std::size_t convCount_ = 0;
  1534. mbstate_t mbState_;
  1535. ::memset(static_cast<void*>(&mbState_), 0, sizeof(mbState_));
  1536. wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_);
  1537. # endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS)
  1538. return buff_;
  1539. }
  1540. };
  1541. /// @brief Operating System helper static class used internally. You should not use it.
  1542. class OS : base::StaticClass
  1543. {
  1544. public:
  1545. #if ELPP_OS_WINDOWS
  1546. /// @brief Gets environment variables for Windows based OS.
  1547. /// We are not using <code>getenv(const char*)</code> because of CRT deprecation
  1548. /// @param varname Variable name to get environment variable value for
  1549. /// @return If variable exist the value of it otherwise nullptr
  1550. static const char* getWindowsEnvironmentVariable(const char* varname)
  1551. {
  1552. const DWORD bufferLen = 50;
  1553. static char buffer[bufferLen];
  1554. if(GetEnvironmentVariableA(varname, buffer, bufferLen))
  1555. {
  1556. return buffer;
  1557. }
  1558. return nullptr;
  1559. }
  1560. #endif // ELPP_OS_WINDOWS
  1561. #if ELPP_OS_ANDROID
  1562. /// @brief Reads android property value
  1563. static inline std::string getProperty(const char* prop)
  1564. {
  1565. char propVal[PROP_VALUE_MAX + 1];
  1566. int ret = __system_property_get(prop, propVal);
  1567. return ret == 0 ? std::string() : std::string(propVal);
  1568. }
  1569. /// @brief Reads android device name
  1570. static std::string getDeviceName(void)
  1571. {
  1572. std::stringstream ss;
  1573. std::string manufacturer = getProperty("ro.product.manufacturer");
  1574. std::string model = getProperty("ro.product.model");
  1575. if(manufacturer.empty() || model.empty())
  1576. {
  1577. return std::string();
  1578. }
  1579. ss << manufacturer << "-" << model;
  1580. return ss.str();
  1581. }
  1582. #endif // ELPP_OS_ANDROID
  1583. /// @brief Runs command on terminal and returns the output.
  1584. ///
  1585. /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned.
  1586. /// @param command Bash command
  1587. /// @return Result of bash output or empty string if no result found.
  1588. static const std::string getBashOutput(const char* command)
  1589. {
  1590. #if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN)
  1591. if(command == nullptr)
  1592. {
  1593. return std::string();
  1594. }
  1595. FILE* proc = nullptr;
  1596. if((proc = popen(command, "r")) == nullptr)
  1597. {
  1598. ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true);
  1599. return std::string();
  1600. }
  1601. char hBuff[4096];
  1602. if(fgets(hBuff, sizeof(hBuff), proc) != nullptr)
  1603. {
  1604. pclose(proc);
  1605. if(hBuff[strlen(hBuff) - 1] == '\n')
  1606. {
  1607. hBuff[strlen(hBuff) - 1] = '\0';
  1608. }
  1609. return std::string(hBuff);
  1610. }
  1611. return std::string();
  1612. #else
  1613. ELPP_UNUSED(command);
  1614. return std::string();
  1615. #endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN)
  1616. }
  1617. /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++)
  1618. /// @param variableName Environment variable name
  1619. /// @param defaultVal If no environment variable or value found the value to return by default
  1620. /// @param alternativeBashCommand If environment variable not found what would be alternative bash command
  1621. /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami'
  1622. static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, const char* alternativeBashCommand = nullptr)
  1623. {
  1624. #if ELPP_OS_UNIX
  1625. const char* val = getenv(variableName);
  1626. #elif ELPP_OS_WINDOWS
  1627. const char* val = getWindowsEnvironmentVariable(variableName);
  1628. #endif // ELPP_OS_UNIX
  1629. if((val == nullptr) || ((strcmp(val, "") == 0)))
  1630. {
  1631. #if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH)
  1632. // Try harder on unix-based systems
  1633. std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand);
  1634. if(valBash.empty())
  1635. {
  1636. return std::string(defaultVal);
  1637. }
  1638. else
  1639. {
  1640. return valBash;
  1641. }
  1642. #elif ELPP_OS_WINDOWS || ELPP_OS_UNIX
  1643. ELPP_UNUSED(alternativeBashCommand);
  1644. return std::string(defaultVal);
  1645. #endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH)
  1646. }
  1647. return std::string(val);
  1648. }
  1649. /// @brief Gets current username.
  1650. static inline std::string currentUser(void)
  1651. {
  1652. #if ELPP_OS_UNIX && !ELPP_OS_ANDROID
  1653. return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami");
  1654. #elif ELPP_OS_WINDOWS
  1655. return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser);
  1656. #elif ELPP_OS_ANDROID
  1657. ELPP_UNUSED(base::consts::kUnknownUser);
  1658. return std::string("android");
  1659. #else
  1660. return std::string();
  1661. #endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID
  1662. }
  1663. /// @brief Gets current host name or computer name.
  1664. ///
  1665. /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen
  1666. static inline std::string currentHost(void)
  1667. {
  1668. #if ELPP_OS_UNIX && !ELPP_OS_ANDROID
  1669. return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname");
  1670. #elif ELPP_OS_WINDOWS
  1671. return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost);
  1672. #elif ELPP_OS_ANDROID
  1673. ELPP_UNUSED(base::consts::kUnknownHost);
  1674. return getDeviceName();
  1675. #else
  1676. return std::string();
  1677. #endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID
  1678. }
  1679. /// @brief Whether or not terminal supports colors
  1680. static inline bool termSupportsColor(void)
  1681. {
  1682. std::string term = getEnvironmentVariable("TERM", "");
  1683. return term == "xterm" || term == "xterm-color" || term == "xterm-256color" ||
  1684. term == "screen" || term == "linux" || term == "cygwin";
  1685. }
  1686. };
  1687. extern std::string s_currentUser;
  1688. extern std::string s_currentHost;
  1689. extern bool s_termSupportsColor;
  1690. #define ELPP_INITI_BASIC_DECLR \
  1691. namespace el {\
  1692. namespace base {\
  1693. namespace utils {\
  1694. std::string s_currentUser = el::base::utils::OS::currentUser(); \
  1695. std::string s_currentHost = el::base::utils::OS::currentHost(); \
  1696. bool s_termSupportsColor = el::base::utils::OS::termSupportsColor(); \
  1697. }\
  1698. }\
  1699. }
  1700. /// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str
  1701. class DateTime : base::StaticClass
  1702. {
  1703. public:
  1704. /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current millisecond.
  1705. ///
  1706. /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided
  1707. /// @param [in,out] tv Pointer that gets updated
  1708. static void gettimeofday(struct timeval* tv)
  1709. {
  1710. #if ELPP_OS_WINDOWS
  1711. if(tv != nullptr)
  1712. {
  1713. # if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS)
  1714. const unsigned __int64 delta_ = 11644473600000000Ui64;
  1715. # else
  1716. const unsigned __int64 delta_ = 11644473600000000ULL;
  1717. # endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS)
  1718. const double secOffSet = 0.000001;
  1719. const unsigned long usecOffSet = 1000000;
  1720. FILETIME fileTime;
  1721. GetSystemTimeAsFileTime(&fileTime);
  1722. unsigned __int64 present = 0;
  1723. present |= fileTime.dwHighDateTime;
  1724. present = present << 32;
  1725. present |= fileTime.dwLowDateTime;
  1726. present /= 10; // mic-sec
  1727. // Subtract the difference
  1728. present -= delta_;
  1729. tv->tv_sec = static_cast<long>(present * secOffSet);
  1730. tv->tv_usec = static_cast<long>(present % usecOffSet);
  1731. }
  1732. #else
  1733. ::gettimeofday(tv, nullptr);
  1734. #endif // ELPP_OS_WINDOWS
  1735. }
  1736. /// @brief Get current date and time with milliseconds
  1737. /// @returns struct tm about now time.
  1738. static inline struct ::tm getCurrentTm()
  1739. {
  1740. struct timeval currTime;
  1741. gettimeofday(&currTime);
  1742. struct ::tm timeInfo;
  1743. buildTimeInfo(&currTime, &timeInfo);
  1744. return timeInfo;
  1745. }
  1746. /// @brief Gets current date and time with milliseconds.
  1747. /// @param format User provided date/time format
  1748. /// @param msWidth A pointer to base::MillisecondsWidth from configuration (non-null)
  1749. /// @returns string based date time in specified format.
  1750. static inline std::string getDateTime(const char* format, const base::MillisecondsWidth* msWidth)
  1751. {
  1752. struct timeval currTime;
  1753. gettimeofday(&currTime);
  1754. struct ::tm timeInfo;
  1755. buildTimeInfo(&currTime, &timeInfo);
  1756. const int kBuffSize = 30;
  1757. char buff_[kBuffSize] = "";
  1758. parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast<std::size_t>(currTime.tv_usec / msWidth->m_offset), msWidth);
  1759. return std::string(buff_);
  1760. }
  1761. /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc
  1762. static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit)
  1763. {
  1764. double result = static_cast<double>(time);
  1765. base::type::EnumType start = static_cast<base::type::EnumType>(timestampUnit);
  1766. const base::type::char_t* unit = base::consts::kTimeFormats[start].unit;
  1767. for(base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i)
  1768. {
  1769. if(result <= base::consts::kTimeFormats[i].value)
  1770. {
  1771. break;
  1772. }
  1773. result /= base::consts::kTimeFormats[i].value;
  1774. unit = base::consts::kTimeFormats[i + 1].unit;
  1775. }
  1776. base::type::stringstream_t ss;
  1777. ss << result << " " << unit;
  1778. return ss.str();
  1779. }
  1780. /// @brief Gets time difference in milli/micro second depending on timestampUnit
  1781. static inline unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, base::TimestampUnit timestampUnit)
  1782. {
  1783. if(timestampUnit == base::TimestampUnit::Microsecond)
  1784. {
  1785. return static_cast<unsigned long long>(static_cast<unsigned long long>(1000000 * endTime.tv_sec + endTime.tv_usec) -
  1786. static_cast<unsigned long long>(1000000 * startTime.tv_sec + startTime.tv_usec));
  1787. }
  1788. else
  1789. {
  1790. return static_cast<unsigned long long>((((endTime.tv_sec - startTime.tv_sec) * 1000000) + (endTime.tv_usec - startTime.tv_usec)) / 1000);
  1791. }
  1792. }
  1793. private:
  1794. static inline struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo)
  1795. {
  1796. #if ELPP_OS_UNIX
  1797. time_t rawTime = currTime->tv_sec;
  1798. ::localtime_r(&rawTime, timeInfo);
  1799. return timeInfo;
  1800. #else
  1801. # if ELPP_COMPILER_MSVC
  1802. ELPP_UNUSED(currTime);
  1803. time_t t;
  1804. _time64(&t);
  1805. localtime_s(timeInfo, &t);
  1806. return timeInfo;
  1807. # else
  1808. // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method
  1809. time_t rawTime = currTime->tv_sec;
  1810. struct tm* tmInf = localtime(&rawTime);
  1811. *timeInfo = *tmInf;
  1812. return timeInfo;
  1813. # endif // ELPP_COMPILER_MSVC
  1814. #endif // ELPP_OS_UNIX
  1815. }
  1816. static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo,
  1817. std::size_t msec, const base::MillisecondsWidth* msWidth)
  1818. {
  1819. const char* bufLim = buf + bufSz;
  1820. for(; *format; ++format)
  1821. {
  1822. if(*format == base::consts::kFormatSpecifierChar)
  1823. {
  1824. switch(*++format)
  1825. {
  1826. case base::consts::kFormatSpecifierChar: // Escape
  1827. break;
  1828. case '\0': // End
  1829. --format;
  1830. break;
  1831. case 'd': // Day
  1832. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim);
  1833. continue;
  1834. case 'a': // Day of week (short)
  1835. buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim);
  1836. continue;
  1837. case 'A': // Day of week (long)
  1838. buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim);
  1839. continue;
  1840. case 'M': // month
  1841. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim);
  1842. continue;
  1843. case 'b': // month (short)
  1844. buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim);
  1845. continue;
  1846. case 'B': // month (long)
  1847. buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim);
  1848. continue;
  1849. case 'y': // year (two digits)
  1850. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim);
  1851. continue;
  1852. case 'Y': // year (four digits)
  1853. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim);
  1854. continue;
  1855. case 'h': // hour (12-hour)
  1856. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim);
  1857. continue;
  1858. case 'H': // hour (24-hour)
  1859. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim);
  1860. continue;
  1861. case 'm': // minute
  1862. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim);
  1863. continue;
  1864. case 's': // second
  1865. buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim);
  1866. continue;
  1867. case 'z': // milliseconds
  1868. case 'g':
  1869. buf = base::utils::Str::convertAndAddToBuff(msec, msWidth->m_width, buf, bufLim);
  1870. continue;
  1871. case 'F': // AM/PM
  1872. buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim);
  1873. continue;
  1874. default:
  1875. continue;
  1876. }
  1877. }
  1878. if(buf == bufLim) break;
  1879. *buf++ = *format;
  1880. }
  1881. return buf;
  1882. }
  1883. };
  1884. /// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..)
  1885. class CommandLineArgs
  1886. {
  1887. public:
  1888. CommandLineArgs(void)
  1889. {
  1890. setArgs(0, static_cast<char**>(nullptr));
  1891. }
  1892. CommandLineArgs(int argc, const char** argv)
  1893. {
  1894. setArgs(argc, argv);
  1895. }
  1896. CommandLineArgs(int argc, char** argv)
  1897. {
  1898. setArgs(argc, argv);
  1899. }
  1900. virtual ~CommandLineArgs(void)
  1901. {
  1902. }
  1903. /// @brief Sets arguments and parses them
  1904. inline void setArgs(int argc, const char** argv)
  1905. {
  1906. setArgs(argc, const_cast<char**>(argv));
  1907. }
  1908. /// @brief Sets arguments and parses them
  1909. inline void setArgs(int argc, char** argv)
  1910. {
  1911. m_params.clear();
  1912. m_paramsWithValue.clear();
  1913. if(argc == 0 || argv == nullptr)
  1914. {
  1915. return;
  1916. }
  1917. m_argc = argc;
  1918. m_argv = argv;
  1919. for(int i = 1; i < m_argc; ++i)
  1920. {
  1921. const char* v = (strstr(m_argv[i], "="));
  1922. if(v != nullptr && strlen(v) > 0)
  1923. {
  1924. std::string key = std::string(m_argv[i]);
  1925. key = key.substr(0, key.find_first_of('='));
  1926. if(hasParamWithValue(key.c_str()))
  1927. {
  1928. ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value ["
  1929. << getParamValue(key.c_str()) << "]");
  1930. }
  1931. else
  1932. {
  1933. m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1)));
  1934. }
  1935. }
  1936. if(v == nullptr)
  1937. {
  1938. if(hasParam(m_argv[i]))
  1939. {
  1940. ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists");
  1941. }
  1942. else
  1943. {
  1944. m_params.push_back(std::string(m_argv[i]));
  1945. }
  1946. }
  1947. }
  1948. }
  1949. /// @brief Returns true if arguments contain paramKey with a value (seperated by '=')
  1950. inline bool hasParamWithValue(const char* paramKey) const
  1951. {
  1952. return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end();
  1953. }
  1954. /// @brief Returns value of arguments
  1955. /// @see hasParamWithValue(const char*)
  1956. inline const char* getParamValue(const char* paramKey) const
  1957. {
  1958. return m_paramsWithValue.find(std::string(paramKey))->second.c_str();
  1959. }
  1960. /// @brief Return true if arguments has a param (not having a value) i,e without '='
  1961. inline bool hasParam(const char* paramKey) const
  1962. {
  1963. return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end();
  1964. }
  1965. /// @brief Returns true if no params available. This exclude argv[0]
  1966. inline bool empty(void) const
  1967. {
  1968. return m_params.empty() && m_paramsWithValue.empty();
  1969. }
  1970. /// @brief Returns total number of arguments. This exclude argv[0]
  1971. inline std::size_t size(void) const
  1972. {
  1973. return m_params.size() + m_paramsWithValue.size();
  1974. }
  1975. inline friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c)
  1976. {
  1977. for(int i = 1; i < c.m_argc; ++i)
  1978. {
  1979. os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]");
  1980. if(i < c.m_argc - 1)
  1981. {
  1982. os << ELPP_LITERAL(" ");
  1983. }
  1984. }
  1985. return os;
  1986. }
  1987. private:
  1988. int m_argc;
  1989. char** m_argv;
  1990. std::map<std::string, std::string> m_paramsWithValue;
  1991. std::vector<std::string> m_params;
  1992. };
  1993. /// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type.
  1994. ///
  1995. /// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement
  1996. /// unregisterAll() and deepCopy(const AbstractRegistry<T_Ptr, Container>&) and write registerNew() method according to container
  1997. /// and few more methods; get() to find element, unregister() to unregister single entry.
  1998. /// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation.
  1999. template <typename T_Ptr, typename Container>
  2000. class AbstractRegistry : public base::threading::ThreadSafe
  2001. {
  2002. public:
  2003. typedef typename Container::iterator iterator;
  2004. typedef typename Container::const_iterator const_iterator;
  2005. /// @brief Default constructor
  2006. AbstractRegistry(void)
  2007. {
  2008. }
  2009. /// @brief Move constructor that is useful for base classes
  2010. AbstractRegistry(AbstractRegistry&& sr)
  2011. {
  2012. if(this == &sr)
  2013. {
  2014. return;
  2015. }
  2016. unregisterAll();
  2017. m_list = std::move(sr.m_list);
  2018. }
  2019. bool operator==(const AbstractRegistry<T_Ptr, Container>& other)
  2020. {
  2021. if(size() != other.size())
  2022. {
  2023. return false;
  2024. }
  2025. for(std::size_t i = 0; i < m_list.size(); ++i)
  2026. {
  2027. if(m_list.at(i) != other.m_list.at(i))
  2028. {
  2029. return false;
  2030. }
  2031. }
  2032. return true;
  2033. }
  2034. bool operator!=(const AbstractRegistry<T_Ptr, Container>& other)
  2035. {
  2036. if(size() != other.size())
  2037. {
  2038. return true;
  2039. }
  2040. for(std::size_t i = 0; i < m_list.size(); ++i)
  2041. {
  2042. if(m_list.at(i) != other.m_list.at(i))
  2043. {
  2044. return true;
  2045. }
  2046. }
  2047. return false;
  2048. }
  2049. /// @brief Assignment move operator
  2050. AbstractRegistry& operator=(AbstractRegistry&& sr)
  2051. {
  2052. if(this == &sr)
  2053. {
  2054. return *this;
  2055. }
  2056. unregisterAll();
  2057. m_list = std::move(sr.m_list);
  2058. return *this;
  2059. }
  2060. virtual ~AbstractRegistry(void)
  2061. {
  2062. }
  2063. /// @return Iterator pointer from start of repository
  2064. virtual inline iterator begin(void) ELPP_FINAL
  2065. {
  2066. return m_list.begin();
  2067. }
  2068. /// @return Iterator pointer from end of repository
  2069. virtual inline iterator end(void) ELPP_FINAL
  2070. {
  2071. return m_list.end();
  2072. }
  2073. /// @return Constant iterator pointer from start of repository
  2074. virtual inline const_iterator cbegin(void) const ELPP_FINAL
  2075. {
  2076. return m_list.cbegin();
  2077. }
  2078. /// @return End of repository
  2079. virtual inline const_iterator cend(void) const ELPP_FINAL
  2080. {
  2081. return m_list.cend();
  2082. }
  2083. /// @return Whether or not repository is empty
  2084. virtual inline bool empty(void) const ELPP_FINAL
  2085. {
  2086. return m_list.empty();
  2087. }
  2088. /// @return Size of repository
  2089. virtual inline std::size_t size(void) const ELPP_FINAL
  2090. {
  2091. return m_list.size();
  2092. }
  2093. /// @brief Returns underlying container by reference
  2094. virtual inline Container& list(void) ELPP_FINAL
  2095. {
  2096. return m_list;
  2097. }
  2098. /// @brief Returns underlying container by constant reference.
  2099. virtual inline const Container& list(void) const ELPP_FINAL
  2100. {
  2101. return m_list;
  2102. }
  2103. /// @brief Unregisters all the pointers from current repository.
  2104. virtual void unregisterAll(void) = 0;
  2105. protected:
  2106. virtual void deepCopy(const AbstractRegistry<T_Ptr, Container>&) = 0;
  2107. void reinitDeepCopy(const AbstractRegistry<T_Ptr, Container>& sr)
  2108. {
  2109. unregisterAll();
  2110. deepCopy(sr);
  2111. }
  2112. private:
  2113. Container m_list;
  2114. };
  2115. /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version)
  2116. ///
  2117. /// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions)
  2118. /// of AbstractRegistry<T_Ptr, Container>. Any implementation of this class should be
  2119. /// explicitly (by using lock functions)
  2120. template <typename T_Ptr, typename T_Key = const char*>
  2121. class Registry : public AbstractRegistry<T_Ptr, std::map<T_Key, T_Ptr*>>
  2122. {
  2123. public:
  2124. typedef typename Registry<T_Ptr, T_Key>::iterator iterator;
  2125. typedef typename Registry<T_Ptr, T_Key>::const_iterator const_iterator;
  2126. Registry(void)
  2127. {
  2128. }
  2129. /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor.
  2130. Registry(const Registry& sr) : AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>()
  2131. {
  2132. if(this == &sr)
  2133. {
  2134. return;
  2135. }
  2136. this->reinitDeepCopy(sr);
  2137. }
  2138. /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element
  2139. /// @see unregisterAll()
  2140. /// @see deepCopy(const AbstractRegistry&)
  2141. Registry& operator=(const Registry& sr)
  2142. {
  2143. if(this == &sr)
  2144. {
  2145. return *this;
  2146. }
  2147. this->reinitDeepCopy(sr);
  2148. return *this;
  2149. }
  2150. virtual ~Registry(void)
  2151. {
  2152. unregisterAll();
  2153. }
  2154. protected:
  2155. virtual inline void unregisterAll(void) ELPP_FINAL
  2156. {
  2157. if(!this->empty())
  2158. {
  2159. for(auto&& curr : this->list())
  2160. {
  2161. base::utils::safeDelete(curr.second);
  2162. }
  2163. this->list().clear();
  2164. }
  2165. }
  2166. /// @brief Registers new registry to repository.
  2167. virtual inline void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL
  2168. {
  2169. unregister(uniqKey);
  2170. this->list().insert(std::make_pair(uniqKey, ptr));
  2171. }
  2172. /// @brief Unregisters single entry mapped to specified unique key
  2173. inline void unregister(const T_Key& uniqKey)
  2174. {
  2175. T_Ptr* existing = get(uniqKey);
  2176. if(existing != nullptr)
  2177. {
  2178. base::utils::safeDelete(existing);
  2179. this->list().erase(uniqKey);
  2180. }
  2181. }
  2182. /// @brief Gets pointer from repository. If none found, nullptr is returned.
  2183. inline T_Ptr* get(const T_Key& uniqKey)
  2184. {
  2185. iterator it = this->list().find(uniqKey);
  2186. return it == this->list().end()
  2187. ? nullptr
  2188. : it->second;
  2189. }
  2190. private:
  2191. virtual inline void deepCopy(const AbstractRegistry<T_Ptr, std::map<T_Key, T_Ptr*>>& sr) ELPP_FINAL
  2192. {
  2193. for(const_iterator it = sr.cbegin(); it != sr.cend(); ++it)
  2194. {
  2195. registerNew(it->first, new T_Ptr(*it->second));
  2196. }
  2197. }
  2198. };
  2199. /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version)
  2200. ///
  2201. /// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry<T_Ptr, Container>. Any implementation of this class
  2202. /// should be made thread-safe explicitly
  2203. template <typename T_Ptr, typename Pred>
  2204. class RegistryWithPred : public AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>
  2205. {
  2206. public:
  2207. typedef typename RegistryWithPred<T_Ptr, Pred>::iterator iterator;
  2208. typedef typename RegistryWithPred<T_Ptr, Pred>::const_iterator const_iterator;
  2209. RegistryWithPred(void)
  2210. {
  2211. }
  2212. virtual ~RegistryWithPred(void)
  2213. {
  2214. unregisterAll();
  2215. }
  2216. /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor.
  2217. RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>()
  2218. {
  2219. if(this == &sr)
  2220. {
  2221. return;
  2222. }
  2223. this->reinitDeepCopy(sr);
  2224. }
  2225. /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element
  2226. /// @see unregisterAll()
  2227. /// @see deepCopy(const AbstractRegistry&)
  2228. RegistryWithPred& operator=(const RegistryWithPred& sr)
  2229. {
  2230. if(this == &sr)
  2231. {
  2232. return *this;
  2233. }
  2234. this->reinitDeepCopy(sr);
  2235. return *this;
  2236. }
  2237. friend inline base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr)
  2238. {
  2239. for(const_iterator it = sr.list().begin(); it != sr.list().end(); ++it)
  2240. {
  2241. os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n");
  2242. }
  2243. return os;
  2244. }
  2245. protected:
  2246. virtual inline void unregisterAll(void) ELPP_FINAL
  2247. {
  2248. if(!this->empty())
  2249. {
  2250. for(auto&& curr : this->list())
  2251. {
  2252. base::utils::safeDelete(curr);
  2253. }
  2254. this->list().clear();
  2255. }
  2256. }
  2257. virtual void unregister(T_Ptr*& ptr) ELPP_FINAL
  2258. {
  2259. if(ptr)
  2260. {
  2261. iterator iter = this->begin();
  2262. for(; iter != this->end(); ++iter)
  2263. {
  2264. if(ptr == *iter)
  2265. {
  2266. break;
  2267. }
  2268. }
  2269. if(iter != this->end() && *iter != nullptr)
  2270. {
  2271. this->list().erase(iter);
  2272. base::utils::safeDelete(*iter);
  2273. }
  2274. }
  2275. }
  2276. virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL
  2277. {
  2278. this->list().push_back(ptr);
  2279. }
  2280. /// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate
  2281. /// in order to validate pointer.
  2282. template <typename T, typename T2>
  2283. inline T_Ptr* get(const T& arg1, const T2 arg2)
  2284. {
  2285. iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2));
  2286. if(iter != this->list().end() && *iter != nullptr)
  2287. {
  2288. return *iter;
  2289. }
  2290. return nullptr;
  2291. }
  2292. private:
  2293. virtual inline void deepCopy(const AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>& sr)
  2294. {
  2295. for(const_iterator it = sr.list().begin(); it != sr.list().end(); ++it)
  2296. {
  2297. registerNew(new T_Ptr(**it));
  2298. }
  2299. }
  2300. };
  2301. } // namespace utils
  2302. } // namespace base
  2303. /// @brief Base of Easylogging++ friendly class
  2304. ///
  2305. /// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const`
  2306. class Loggable
  2307. {
  2308. public:
  2309. virtual ~Loggable(void)
  2310. {
  2311. }
  2312. virtual void log(el::base::type::ostream_t&) const = 0;
  2313. private:
  2314. friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable)
  2315. {
  2316. loggable.log(os);
  2317. return os;
  2318. }
  2319. };
  2320. namespace base {
  2321. /// @brief Represents log format containing flags and date format. This is used internally to start initial log
  2322. class LogFormat : public Loggable
  2323. {
  2324. public:
  2325. LogFormat(void) :
  2326. m_level(Level::Unknown),
  2327. m_userFormat(base::type::string_t()),
  2328. m_format(base::type::string_t()),
  2329. m_dateTimeFormat(std::string()),
  2330. m_flags(0x0)
  2331. {
  2332. }
  2333. LogFormat(Level level, const base::type::string_t& format)
  2334. : m_level(level), m_userFormat(format)
  2335. {
  2336. parseFromFormat(m_userFormat);
  2337. }
  2338. LogFormat(const LogFormat& logFormat)
  2339. {
  2340. m_level = logFormat.m_level;
  2341. m_userFormat = logFormat.m_userFormat;
  2342. m_format = logFormat.m_format;
  2343. m_dateTimeFormat = logFormat.m_dateTimeFormat;
  2344. m_flags = logFormat.m_flags;
  2345. }
  2346. LogFormat(LogFormat&& logFormat)
  2347. {
  2348. m_level = std::move(logFormat.m_level);
  2349. m_userFormat = std::move(logFormat.m_userFormat);
  2350. m_format = std::move(logFormat.m_format);
  2351. m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat);
  2352. m_flags = std::move(logFormat.m_flags);
  2353. }
  2354. LogFormat& operator=(const LogFormat& logFormat)
  2355. {
  2356. m_level = logFormat.m_level;
  2357. m_userFormat = logFormat.m_userFormat;
  2358. m_dateTimeFormat = logFormat.m_dateTimeFormat;
  2359. m_flags = logFormat.m_flags;
  2360. return *this;
  2361. }
  2362. virtual ~LogFormat(void)
  2363. {
  2364. }
  2365. inline bool operator==(const LogFormat& other)
  2366. {
  2367. return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format &&
  2368. m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags;
  2369. }
  2370. /// @brief Updates format to be used while logging.
  2371. /// @param userFormat User provided format
  2372. void parseFromFormat(const base::type::string_t& userFormat)
  2373. {
  2374. // We make copy because we will be changing the format
  2375. // i.e, removing user provided date format from original format
  2376. // and then storing it.
  2377. base::type::string_t formatCopy = userFormat;
  2378. m_flags = 0x0;
  2379. auto conditionalAddFlag = [&](const base::type::char_t* specifier, base::FormatFlags flag)
  2380. {
  2381. std::size_t foundAt = base::type::string_t::npos;
  2382. while((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos)
  2383. {
  2384. if(foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar)
  2385. {
  2386. if(hasFlag(flag))
  2387. {
  2388. // If we already have flag we remove the escape chars so that '%%' is turned to '%'
  2389. // even after specifier resolution - this is because we only replaceFirst specifier
  2390. formatCopy.erase(foundAt > 0 ? foundAt - 1 : 0, 1);
  2391. ++foundAt;
  2392. }
  2393. }
  2394. else
  2395. {
  2396. if(!hasFlag(flag)) addFlag(flag);
  2397. }
  2398. }
  2399. };
  2400. conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName);
  2401. conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level);
  2402. conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort);
  2403. conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId);
  2404. conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId);
  2405. conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File);
  2406. conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase);
  2407. conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line);
  2408. conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location);
  2409. conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function);
  2410. conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User);
  2411. conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host);
  2412. conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage);
  2413. conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel);
  2414. // For date/time we need to extract user's date format first
  2415. std::size_t dateIndex = std::string::npos;
  2416. if((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos)
  2417. {
  2418. while(dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar)
  2419. {
  2420. dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1);
  2421. }
  2422. if(dateIndex != std::string::npos)
  2423. {
  2424. addFlag(base::FormatFlags::DateTime);
  2425. updateDateFormat(dateIndex, formatCopy);
  2426. }
  2427. }
  2428. m_format = formatCopy;
  2429. updateFormatSpec();
  2430. }
  2431. inline Level level(void) const
  2432. {
  2433. return m_level;
  2434. }
  2435. inline const base::type::string_t& userFormat(void) const
  2436. {
  2437. return m_userFormat;
  2438. }
  2439. inline const base::type::string_t& format(void) const
  2440. {
  2441. return m_format;
  2442. }
  2443. inline const std::string& dateTimeFormat(void) const
  2444. {
  2445. return m_dateTimeFormat;
  2446. }
  2447. inline base::type::EnumType flags(void) const
  2448. {
  2449. return m_flags;
  2450. }
  2451. inline bool hasFlag(base::FormatFlags flag) const
  2452. {
  2453. return base::utils::hasFlag(flag, m_flags);
  2454. }
  2455. virtual void log(el::base::type::ostream_t& os) const
  2456. {
  2457. os << m_format;
  2458. }
  2459. protected:
  2460. /// @brief Updates date time format if available in currFormat.
  2461. /// @param index Index where %datetime, %date or %time was found
  2462. /// @param [in,out] currFormat current format that is being used to format
  2463. virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL
  2464. {
  2465. if(hasFlag(base::FormatFlags::DateTime))
  2466. {
  2467. index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier);
  2468. }
  2469. const base::type::char_t* ptr = currFormat.c_str() + index;
  2470. if((currFormat.size() > index) && (ptr[0] == '{'))
  2471. {
  2472. // User has provided format for date/time
  2473. ++ptr;
  2474. int count = 1; // Start by 1 in order to remove starting brace
  2475. std::stringstream ss;
  2476. for(; *ptr; ++ptr, ++count)
  2477. {
  2478. if(*ptr == '}')
  2479. {
  2480. ++count; // In order to remove ending brace
  2481. break;
  2482. }
  2483. ss << *ptr;
  2484. }
  2485. currFormat.erase(index, count);
  2486. m_dateTimeFormat = ss.str();
  2487. }
  2488. else
  2489. {
  2490. // No format provided, use default
  2491. if(hasFlag(base::FormatFlags::DateTime))
  2492. {
  2493. m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat);
  2494. }
  2495. }
  2496. }
  2497. /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level
  2498. virtual void updateFormatSpec(void) ELPP_FINAL
  2499. {
  2500. // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet.
  2501. if(m_level == Level::Debug)
  2502. {
  2503. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2504. base::consts::kDebugLevelLogValue);
  2505. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2506. base::consts::kDebugLevelShortLogValue);
  2507. }
  2508. else if(m_level == Level::Info)
  2509. {
  2510. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2511. base::consts::kInfoLevelLogValue);
  2512. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2513. base::consts::kInfoLevelShortLogValue);
  2514. }
  2515. else if(m_level == Level::Warning)
  2516. {
  2517. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2518. base::consts::kWarningLevelLogValue);
  2519. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2520. base::consts::kWarningLevelShortLogValue);
  2521. }
  2522. else if(m_level == Level::Error)
  2523. {
  2524. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2525. base::consts::kErrorLevelLogValue);
  2526. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2527. base::consts::kErrorLevelShortLogValue);
  2528. }
  2529. else if(m_level == Level::Fatal)
  2530. {
  2531. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2532. base::consts::kFatalLevelLogValue);
  2533. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2534. base::consts::kFatalLevelShortLogValue);
  2535. }
  2536. else if(m_level == Level::Verbose)
  2537. {
  2538. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2539. base::consts::kVerboseLevelLogValue);
  2540. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2541. base::consts::kVerboseLevelShortLogValue);
  2542. }
  2543. else if(m_level == Level::Trace)
  2544. {
  2545. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier,
  2546. base::consts::kTraceLevelLogValue);
  2547. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier,
  2548. base::consts::kTraceLevelShortLogValue);
  2549. }
  2550. if(hasFlag(base::FormatFlags::User))
  2551. {
  2552. std::string s = base::utils::s_currentUser;
  2553. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier,
  2554. base::utils::s_currentUser);
  2555. }
  2556. if(hasFlag(base::FormatFlags::Host))
  2557. {
  2558. base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier,
  2559. base::utils::s_currentHost);
  2560. }
  2561. // Ignore Level::Global and Level::Unknown
  2562. }
  2563. inline void addFlag(base::FormatFlags flag)
  2564. {
  2565. base::utils::addFlag(flag, &m_flags);
  2566. }
  2567. private:
  2568. Level m_level;
  2569. base::type::string_t m_userFormat;
  2570. base::type::string_t m_format;
  2571. std::string m_dateTimeFormat;
  2572. base::type::EnumType m_flags;
  2573. friend class el::Logger; // To resolve loggerId format specifier easily
  2574. };
  2575. } // namespace base
  2576. /// @brief Resolving function for format specifier
  2577. typedef std::function<const char* (void)> FormatSpecifierValueResolver;
  2578. /// @brief User-provided custom format specifier
  2579. /// @see el::Helpers::installCustomFormatSpecifier
  2580. /// @see FormatSpecifierValueResolver
  2581. class CustomFormatSpecifier
  2582. {
  2583. public:
  2584. CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) :
  2585. m_formatSpecifier(formatSpecifier), m_resolver(resolver)
  2586. {
  2587. }
  2588. inline const char* formatSpecifier(void) const
  2589. {
  2590. return m_formatSpecifier;
  2591. }
  2592. inline const FormatSpecifierValueResolver& resolver(void) const
  2593. {
  2594. return m_resolver;
  2595. }
  2596. inline bool operator==(const char* formatSpecifier)
  2597. {
  2598. return strcmp(m_formatSpecifier, formatSpecifier) == 0;
  2599. }
  2600. private:
  2601. const char* m_formatSpecifier;
  2602. FormatSpecifierValueResolver m_resolver;
  2603. };
  2604. /// @brief Represents single configuration that has representing level, configuration type and a string based value.
  2605. ///
  2606. /// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes
  2607. /// and will be parsed later.
  2608. ///
  2609. /// Consider some examples below:
  2610. /// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true");
  2611. /// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048");
  2612. /// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log");
  2613. class Configuration : public Loggable
  2614. {
  2615. public:
  2616. Configuration(const Configuration& c) :
  2617. m_level(c.m_level),
  2618. m_configurationType(c.m_configurationType),
  2619. m_value(c.m_value)
  2620. {
  2621. }
  2622. Configuration& operator=(const Configuration& c)
  2623. {
  2624. m_level = c.m_level;
  2625. m_configurationType = c.m_configurationType;
  2626. m_value = c.m_value;
  2627. return *this;
  2628. }
  2629. virtual ~Configuration(void)
  2630. {
  2631. }
  2632. /// @brief Full constructor used to sets value of configuration
  2633. Configuration(Level level, ConfigurationType configurationType, const std::string& value) :
  2634. m_level(level),
  2635. m_configurationType(configurationType),
  2636. m_value(value)
  2637. {
  2638. }
  2639. /// @brief Gets level of current configuration
  2640. inline Level level(void) const
  2641. {
  2642. return m_level;
  2643. }
  2644. /// @brief Gets configuration type of current configuration
  2645. inline ConfigurationType configurationType(void) const
  2646. {
  2647. return m_configurationType;
  2648. }
  2649. /// @brief Gets string based configuration value
  2650. inline const std::string& value(void) const
  2651. {
  2652. return m_value;
  2653. }
  2654. /// @brief Set string based configuration value
  2655. /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values
  2656. /// use them in quotes. They will be parsed when configuring
  2657. inline void setValue(const std::string& value)
  2658. {
  2659. m_value = value;
  2660. }
  2661. virtual inline void log(el::base::type::ostream_t& os) const
  2662. {
  2663. os << LevelHelper::convertToString(m_level)
  2664. << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType)
  2665. << ELPP_LITERAL(" = ") << m_value.c_str();
  2666. }
  2667. /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it.
  2668. class Predicate
  2669. {
  2670. public:
  2671. Predicate(Level level, ConfigurationType configurationType) :
  2672. m_level(level),
  2673. m_configurationType(configurationType)
  2674. {
  2675. }
  2676. inline bool operator()(const Configuration* conf) const
  2677. {
  2678. return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType));
  2679. }
  2680. private:
  2681. Level m_level;
  2682. ConfigurationType m_configurationType;
  2683. };
  2684. private:
  2685. Level m_level;
  2686. ConfigurationType m_configurationType;
  2687. std::string m_value;
  2688. };
  2689. /// @brief Thread-safe Configuration repository
  2690. ///
  2691. /// @detail This repository represents configurations for all the levels and configuration type mapped to a value.
  2692. class Configurations : public base::utils::RegistryWithPred<Configuration, Configuration::Predicate>
  2693. {
  2694. public:
  2695. /// @brief Default constructor with empty repository
  2696. Configurations(void) :
  2697. m_configurationFile(std::string()),
  2698. m_isFromFile(false)
  2699. {
  2700. }
  2701. /// @brief Constructor used to set configurations using configuration file.
  2702. /// @param configurationFile Full path to configuration file
  2703. /// @param useDefaultsForRemaining Lets you set the remaining configurations to default.
  2704. /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to.
  2705. /// @see parseFromFile(const std::string&, Configurations* base)
  2706. /// @see setRemainingToDefault()
  2707. Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, Configurations* base = nullptr) :
  2708. m_configurationFile(configurationFile),
  2709. m_isFromFile(false)
  2710. {
  2711. parseFromFile(configurationFile, base);
  2712. if(useDefaultsForRemaining)
  2713. {
  2714. setRemainingToDefault();
  2715. }
  2716. }
  2717. virtual ~Configurations(void)
  2718. {
  2719. }
  2720. /// @brief Parses configuration from file.
  2721. /// @param configurationFile Full path to configuration file
  2722. /// @param base Configurations to base new configuration repository off. This value is used when you want to use
  2723. /// existing Configurations to base all the values and then set rest of configuration via configuration file.
  2724. /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you
  2725. /// do not proceed without successful parse.
  2726. inline bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr)
  2727. {
  2728. // We initial assertion with true because if we have assertion diabled, we want to pass this
  2729. // check and if assertion is enabled we will have values re-assigned any way.
  2730. bool assertionPassed = true;
  2731. ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)),
  2732. "Configuration file [" << configurationFile << "] does not exist!");
  2733. if(!assertionPassed)
  2734. {
  2735. return false;
  2736. }
  2737. bool success = Parser::parseFromFile(configurationFile, this, base);
  2738. m_isFromFile = success;
  2739. return success;
  2740. }
  2741. /// @brief Parse configurations from configuration string.
  2742. ///
  2743. /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary
  2744. /// new line characters are provided.
  2745. /// @param base Configurations to base new configuration repository off. This value is used when you want to use
  2746. /// existing Configurations to base all the values and then set rest of configuration via configuration text.
  2747. /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you
  2748. /// do not proceed without successful parse.
  2749. inline bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr)
  2750. {
  2751. bool success = Parser::parseFromText(configurationsString, this, base);
  2752. if(success)
  2753. {
  2754. m_isFromFile = false;
  2755. }
  2756. return success;
  2757. }
  2758. /// @brief Sets configuration based-off an existing configurations.
  2759. /// @param base Pointer to existing configurations.
  2760. inline void setFromBase(Configurations* base)
  2761. {
  2762. if(base == nullptr || base == this)
  2763. {
  2764. return;
  2765. }
  2766. base::threading::ScopedLock scopedLock(base->lock());
  2767. for(Configuration*& conf : base->list())
  2768. {
  2769. set(conf);
  2770. }
  2771. }
  2772. /// @brief Determines whether or not specified configuration type exists in the repository.
  2773. ///
  2774. /// @detail Returns as soon as first level is found.
  2775. /// @param configurationType Type of configuration to check existence for.
  2776. bool hasConfiguration(ConfigurationType configurationType)
  2777. {
  2778. base::type::EnumType lIndex = LevelHelper::kMinValid;
  2779. bool result = false;
  2780. LevelHelper::forEachLevel(&lIndex, [&](void) -> bool
  2781. {
  2782. if(hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType))
  2783. {
  2784. result = true;
  2785. }
  2786. return result;
  2787. });
  2788. return result;
  2789. }
  2790. /// @brief Determines whether or not specified configuration type exists for specified level
  2791. /// @param level Level to check
  2792. /// @param configurationType Type of configuration to check existence for.
  2793. inline bool hasConfiguration(Level level, ConfigurationType configurationType)
  2794. {
  2795. base::threading::ScopedLock scopedLock(lock());
  2796. #if ELPP_COMPILER_INTEL
  2797. // We cant specify template types here, Intel C++ throws compilation error
  2798. // "error: type name is not allowed"
  2799. return RegistryWithPred::get(level, configurationType) != nullptr;
  2800. #else
  2801. return RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType) != nullptr;
  2802. #endif // ELPP_COMPILER_INTEL
  2803. }
  2804. /// @brief Sets value of configuration for specified level.
  2805. ///
  2806. /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types
  2807. /// ConfigurationType::MillisecondsWidth and ConfigurationType::PerformanceTracking will be ignored if not set for
  2808. /// Level::Global because these configurations are not dependant on level.
  2809. /// @param level Level to set configuration for (el::Level).
  2810. /// @param configurationType Type of configuration (el::ConfigurationType)
  2811. /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string
  2812. /// from users' point of view. This is then parsed later to be used internally.
  2813. /// @see Configuration::setValue(const std::string& value)
  2814. /// @see el::Level
  2815. /// @see el::ConfigurationType
  2816. inline void set(Level level, ConfigurationType configurationType, const std::string& value)
  2817. {
  2818. base::threading::ScopedLock scopedLock(lock());
  2819. unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex
  2820. if(level == Level::Global)
  2821. {
  2822. unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either
  2823. }
  2824. }
  2825. /// @brief Sets single configuration based on other single configuration.
  2826. /// @see set(Level level, ConfigurationType configurationType, const std::string& value)
  2827. inline void set(Configuration* conf)
  2828. {
  2829. if(conf == nullptr)
  2830. {
  2831. return;
  2832. }
  2833. set(conf->level(), conf->configurationType(), conf->value());
  2834. }
  2835. inline Configuration* get(Level level, ConfigurationType configurationType)
  2836. {
  2837. base::threading::ScopedLock scopedLock(lock());
  2838. return RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType);
  2839. }
  2840. /// @brief Sets configuration for all levels.
  2841. /// @param configurationType Type of configuration
  2842. /// @param value String based value
  2843. /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value)
  2844. inline void setGlobally(ConfigurationType configurationType, const std::string& value)
  2845. {
  2846. setGlobally(configurationType, value, false);
  2847. }
  2848. /// @brief Clears repository so that all the configurations are unset
  2849. inline void clear(void)
  2850. {
  2851. base::threading::ScopedLock scopedLock(lock());
  2852. unregisterAll();
  2853. }
  2854. /// @brief Gets configuration file used in parsing this configurations.
  2855. ///
  2856. /// @detail If this repository was set manually or by text this returns empty string.
  2857. inline const std::string& configurationFile(void) const
  2858. {
  2859. return m_configurationFile;
  2860. }
  2861. /// @brief Sets configurations to "factory based" configurations.
  2862. void setToDefault(void)
  2863. {
  2864. setGlobally(ConfigurationType::Enabled, std::string("true"), true);
  2865. #if !defined(ELPP_NO_DEFAULT_LOG_FILE)
  2866. setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true);
  2867. #else
  2868. ELPP_UNUSED(base::consts::kDefaultLogFile);
  2869. #endif // !defined(ELPP_NO_DEFAULT_LOG_FILE)
  2870. setGlobally(ConfigurationType::ToFile, std::string("true"), true);
  2871. setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true);
  2872. setGlobally(ConfigurationType::MillisecondsWidth, std::string("3"), true);
  2873. setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true);
  2874. setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true);
  2875. setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true);
  2876. setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true);
  2877. set(Level::Debug, ConfigurationType::Format, std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg"));
  2878. // INFO and WARNING are set to default by Level::Global
  2879. set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"));
  2880. set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"));
  2881. set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg"));
  2882. set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg"));
  2883. }
  2884. /// @brief Lets you set the remaining configurations to default.
  2885. ///
  2886. /// @detail By remaining, it means that the level/type a configuration does not exist for.
  2887. /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets
  2888. /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e,
  2889. /// true. If you dont do this explicitley (either by calling this function or by using second param in Constructor
  2890. /// and try to access a value, an error is thrown
  2891. void setRemainingToDefault(void)
  2892. {
  2893. base::threading::ScopedLock scopedLock(lock());
  2894. unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true"));
  2895. #if !defined(ELPP_NO_DEFAULT_LOG_FILE)
  2896. unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile));
  2897. #endif // !defined(ELPP_NO_DEFAULT_LOG_FILE)
  2898. unsafeSetIfNotExist(Level::Global, ConfigurationType::ToFile, std::string("true"));
  2899. unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true"));
  2900. unsafeSetIfNotExist(Level::Global, ConfigurationType::MillisecondsWidth, std::string("3"));
  2901. unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true"));
  2902. unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0"));
  2903. unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"));
  2904. unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format,
  2905. std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg"));
  2906. // INFO and WARNING are set to default by Level::Global
  2907. unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"));
  2908. unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"));
  2909. unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg"));
  2910. unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg"));
  2911. }
  2912. /// @brief Parser used internally to parse configurations from file or text.
  2913. ///
  2914. /// @detail This class makes use of base::utils::Str.
  2915. /// You should not need this unless you are working on some tool for Easylogging++
  2916. class Parser : base::StaticClass
  2917. {
  2918. public:
  2919. /// @brief Parses configuration from file.
  2920. /// @param configurationFile Full path to configuration file
  2921. /// @param sender Sender configurations pointer. Usually 'this' is used from calling class
  2922. /// @param base Configurations to base new configuration repository off. This value is used when you want to use
  2923. /// existing Configurations to base all the values and then set rest of configuration via configuration file.
  2924. /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you
  2925. /// do not proceed without successful parse.
  2926. static bool parseFromFile(const std::string& configurationFile, Configurations* sender, Configurations* base = nullptr)
  2927. {
  2928. sender->setFromBase(base);
  2929. std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in);
  2930. ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing.");
  2931. bool parsedSuccessfully = false;
  2932. std::string line = std::string();
  2933. Level currLevel = Level::Unknown;
  2934. std::string currConfigStr = std::string();
  2935. std::string currLevelStr = std::string();
  2936. while(fileStream_.good())
  2937. {
  2938. std::getline(fileStream_, line);
  2939. parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender);
  2940. ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line);
  2941. }
  2942. return parsedSuccessfully;
  2943. }
  2944. /// @brief Parse configurations from configuration string.
  2945. ///
  2946. /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary
  2947. /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you
  2948. /// do not proceed without successful parse (This is recommended)
  2949. /// @param configurationsString
  2950. /// @param sender Sender configurations pointer. Usually 'this' is used from calling class
  2951. /// @param base Configurations to base new configuration repository off. This value is used when you want to use
  2952. /// existing Configurations to base all the values and then set rest of configuration via configuration text.
  2953. /// @return True if successfully parsed, false otherwise.
  2954. static bool parseFromText(const std::string& configurationsString, Configurations* sender, Configurations* base = nullptr)
  2955. {
  2956. sender->setFromBase(base);
  2957. bool parsedSuccessfully = false;
  2958. std::stringstream ss(configurationsString);
  2959. std::string line = std::string();
  2960. Level currLevel = Level::Unknown;
  2961. std::string currConfigStr = std::string();
  2962. std::string currLevelStr = std::string();
  2963. while(std::getline(ss, line))
  2964. {
  2965. parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender);
  2966. ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line);
  2967. }
  2968. return parsedSuccessfully;
  2969. }
  2970. private:
  2971. friend class el::Loggers;
  2972. static void ignoreComments(std::string* line)
  2973. {
  2974. std::size_t foundAt = 0;
  2975. std::size_t quotesStart = line->find("\"");
  2976. std::size_t quotesEnd = std::string::npos;
  2977. if(quotesStart != std::string::npos)
  2978. {
  2979. quotesEnd = line->find("\"", quotesStart + 1);
  2980. while(quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\')
  2981. {
  2982. // Do not erase slash yet - we will erase it in parseLine(..) while loop
  2983. quotesEnd = line->find("\"", quotesEnd + 2);
  2984. }
  2985. }
  2986. if((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos)
  2987. {
  2988. if(foundAt < quotesEnd)
  2989. {
  2990. foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1);
  2991. }
  2992. *line = line->substr(0, foundAt);
  2993. }
  2994. }
  2995. static inline bool isLevel(const std::string& line)
  2996. {
  2997. return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel));
  2998. }
  2999. static inline bool isComment(const std::string& line)
  3000. {
  3001. return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment));
  3002. }
  3003. static inline bool isConfig(const std::string& line)
  3004. {
  3005. std::size_t assignment = line.find('=');
  3006. return line != "" &&
  3007. (line[0] >= 65 || line[0] <= 90 || line[0] >= 97 || line[0] <= 122) &&
  3008. (assignment != std::string::npos) &&
  3009. (line.size() > assignment);
  3010. }
  3011. static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, Configurations* conf)
  3012. {
  3013. ConfigurationType currConfig = ConfigurationType::Unknown;
  3014. std::string currValue = std::string();
  3015. *line = base::utils::Str::trim(*line);
  3016. if(isComment(*line)) return true;
  3017. ignoreComments(line);
  3018. *line = base::utils::Str::trim(*line);
  3019. if(line->empty())
  3020. {
  3021. // Comment ignored
  3022. return true;
  3023. }
  3024. if(isLevel(*line))
  3025. {
  3026. if(line->size() <= 2)
  3027. {
  3028. return true;
  3029. }
  3030. *currLevelStr = line->substr(1, line->size() - 2);
  3031. *currLevelStr = base::utils::Str::toUpper(*currLevelStr);
  3032. *currLevelStr = base::utils::Str::trim(*currLevelStr);
  3033. *currLevel = LevelHelper::convertFromString(currLevelStr->c_str());
  3034. return true;
  3035. }
  3036. if(isConfig(*line))
  3037. {
  3038. std::size_t assignment = line->find('=');
  3039. *currConfigStr = line->substr(0, assignment);
  3040. *currConfigStr = base::utils::Str::toUpper(*currConfigStr);
  3041. *currConfigStr = base::utils::Str::trim(*currConfigStr);
  3042. currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str());
  3043. currValue = line->substr(assignment + 1);
  3044. currValue = base::utils::Str::trim(currValue);
  3045. std::size_t quotesStart = currValue.find("\"", 0);
  3046. std::size_t quotesEnd = std::string::npos;
  3047. if(quotesStart != std::string::npos)
  3048. {
  3049. quotesEnd = currValue.find("\"", quotesStart + 1);
  3050. while(quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\')
  3051. {
  3052. currValue = currValue.erase(quotesEnd - 1, 1);
  3053. quotesEnd = currValue.find("\"", quotesEnd + 2);
  3054. }
  3055. }
  3056. if(quotesStart != std::string::npos && quotesEnd != std::string::npos)
  3057. {
  3058. // Quote provided - check and strip if valid
  3059. ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in ["
  3060. << currConfigStr << "]");
  3061. ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]");
  3062. if((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd))
  3063. {
  3064. // Explicit check in case if assertion is disabled
  3065. currValue = currValue.substr(quotesStart + 1, quotesEnd - 1);
  3066. }
  3067. }
  3068. }
  3069. ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]");
  3070. ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]");
  3071. if(*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown)
  3072. {
  3073. return false; // unrecognizable level or config
  3074. }
  3075. conf->set(*currLevel, currConfig, currValue);
  3076. return true;
  3077. }
  3078. };
  3079. private:
  3080. std::string m_configurationFile;
  3081. bool m_isFromFile;
  3082. friend class el::Loggers;
  3083. /// @brief Unsafely sets configuration if does not already exist
  3084. void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value)
  3085. {
  3086. Configuration* conf = RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType);
  3087. if(conf == nullptr)
  3088. {
  3089. unsafeSet(level, configurationType, value);
  3090. }
  3091. }
  3092. /// @brief Thread unsafe set
  3093. void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value)
  3094. {
  3095. Configuration* conf = RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType);
  3096. if(conf == nullptr)
  3097. {
  3098. registerNew(new Configuration(level, configurationType, value));
  3099. }
  3100. else
  3101. {
  3102. conf->setValue(value);
  3103. }
  3104. if(level == Level::Global)
  3105. {
  3106. unsafeSetGlobally(configurationType, value, false);
  3107. }
  3108. }
  3109. /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true
  3110. /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value)
  3111. void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel)
  3112. {
  3113. if(includeGlobalLevel)
  3114. {
  3115. set(Level::Global, configurationType, value);
  3116. }
  3117. base::type::EnumType lIndex = LevelHelper::kMinValid;
  3118. LevelHelper::forEachLevel(&lIndex, [&](void) -> bool
  3119. {
  3120. set(LevelHelper::castFromInt(lIndex), configurationType, value);
  3121. return false; // Do not break lambda function yet as we need to set all levels regardless
  3122. });
  3123. }
  3124. /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true
  3125. /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value)
  3126. void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel)
  3127. {
  3128. if(includeGlobalLevel)
  3129. {
  3130. unsafeSet(Level::Global, configurationType, value);
  3131. }
  3132. base::type::EnumType lIndex = LevelHelper::kMinValid;
  3133. LevelHelper::forEachLevel(&lIndex, [&](void) -> bool
  3134. {
  3135. unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value);
  3136. return false; // Do not break lambda function yet as we need to set all levels regardless
  3137. });
  3138. }
  3139. };
  3140. namespace base {
  3141. typedef std::shared_ptr<base::type::fstream_t> FileStreamPtr;
  3142. typedef std::map<std::string, FileStreamPtr> LogStreamsReferenceMap;
  3143. /// @brief Configurations with data types.
  3144. ///
  3145. /// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations.
  3146. /// This is to perform faster while writing logs using correct configurations.
  3147. ///
  3148. /// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class)
  3149. class TypedConfigurations : public base::threading::ThreadSafe
  3150. {
  3151. public:
  3152. /// @brief Constructor to initialize (construct) the object off el::Configurations
  3153. /// @param configurations Configurations pointer/reference to base this typed configurations off.
  3154. /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference()
  3155. TypedConfigurations(Configurations* configurations, base::LogStreamsReferenceMap* logStreamsReference)
  3156. {
  3157. m_configurations = configurations;
  3158. m_logStreamsReference = logStreamsReference;
  3159. build(m_configurations);
  3160. }
  3161. TypedConfigurations(const TypedConfigurations& other)
  3162. {
  3163. this->m_configurations = other.m_configurations;
  3164. this->m_logStreamsReference = other.m_logStreamsReference;
  3165. build(m_configurations);
  3166. }
  3167. virtual ~TypedConfigurations(void)
  3168. {
  3169. }
  3170. const Configurations* configurations(void) const
  3171. {
  3172. return m_configurations;
  3173. }
  3174. inline bool enabled(Level level)
  3175. {
  3176. return getConfigByVal<bool>(level, &m_enabledMap, "enabled");
  3177. }
  3178. inline bool toFile(Level level)
  3179. {
  3180. return getConfigByVal<bool>(level, &m_toFileMap, "toFile");
  3181. }
  3182. inline const std::string& filename(Level level)
  3183. {
  3184. return getConfigByRef<std::string>(level, &m_filenameMap, "filename");
  3185. }
  3186. inline bool toStandardOutput(Level level)
  3187. {
  3188. return getConfigByVal<bool>(level, &m_toStandardOutputMap, "toStandardOutput");
  3189. }
  3190. inline const base::LogFormat& logFormat(Level level)
  3191. {
  3192. return getConfigByRef<base::LogFormat>(level, &m_logFormatMap, "logFormat");
  3193. }
  3194. inline const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global)
  3195. {
  3196. return getConfigByRef<base::MillisecondsWidth>(level, &m_millisecondsWidthMap, "millisecondsWidth");
  3197. }
  3198. inline bool performanceTracking(Level level = Level::Global)
  3199. {
  3200. return getConfigByVal<bool>(level, &m_performanceTrackingMap, "performanceTracking");
  3201. }
  3202. inline base::type::fstream_t* fileStream(Level level)
  3203. {
  3204. return getConfigByRef<base::FileStreamPtr>(level, &m_fileStreamMap, "fileStream").get();
  3205. }
  3206. inline std::size_t maxLogFileSize(Level level)
  3207. {
  3208. return getConfigByVal<std::size_t>(level, &m_maxLogFileSizeMap, "maxLogFileSize");
  3209. }
  3210. inline std::size_t logFlushThreshold(Level level)
  3211. {
  3212. return getConfigByVal<std::size_t>(level, &m_logFlushThresholdMap, "logFlushThreshold");
  3213. }
  3214. private:
  3215. Configurations* m_configurations;
  3216. std::map<Level, bool> m_enabledMap;
  3217. std::map<Level, bool> m_toFileMap;
  3218. std::map<Level, std::string> m_filenameMap;
  3219. std::map<Level, bool> m_toStandardOutputMap;
  3220. std::map<Level, base::LogFormat> m_logFormatMap;
  3221. std::map<Level, base::MillisecondsWidth> m_millisecondsWidthMap;
  3222. std::map<Level, bool> m_performanceTrackingMap;
  3223. std::map<Level, base::FileStreamPtr> m_fileStreamMap;
  3224. std::map<Level, std::size_t> m_maxLogFileSizeMap;
  3225. std::map<Level, std::size_t> m_logFlushThresholdMap;
  3226. base::LogStreamsReferenceMap* m_logStreamsReference;
  3227. std::map<Level, std::string> m_fileFullnameMap; // add to record file base name in config
  3228. std::map<Level, std::size_t> m_fileLastTimeMap; // add to record last time, for changing file name
  3229. friend class el::Helpers;
  3230. friend class el::base::MessageBuilder;
  3231. friend class el::base::Writer;
  3232. friend class el::base::DefaultLogDispatchCallback;
  3233. friend class el::base::LogDispatcher;
  3234. template <typename Conf_T>
  3235. inline Conf_T getConfigByVal(Level level, const std::map<Level, Conf_T>* confMap, const char* confName)
  3236. {
  3237. base::threading::ScopedLock scopedLock(lock());
  3238. return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope
  3239. }
  3240. template <typename Conf_T>
  3241. inline Conf_T& getConfigByRef(Level level, std::map<Level, Conf_T>* confMap, const char* confName)
  3242. {
  3243. base::threading::ScopedLock scopedLock(lock());
  3244. return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope
  3245. }
  3246. template <typename Conf_T>
  3247. inline Conf_T unsafeGetConfigByVal(Level level, const std::map<Level, Conf_T>* confMap, const char* confName)
  3248. {
  3249. ELPP_UNUSED(confName);
  3250. typename std::map<Level, Conf_T>::const_iterator it = confMap->find(level);
  3251. if(it == confMap->end())
  3252. {
  3253. try
  3254. {
  3255. return confMap->at(Level::Global);
  3256. }
  3257. catch(...)
  3258. {
  3259. ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level ["
  3260. << LevelHelper::convertToString(level) << "]"
  3261. << std::endl << "Please ensure you have properly configured logger.", false);
  3262. return Conf_T();
  3263. }
  3264. }
  3265. return it->second;
  3266. }
  3267. template <typename Conf_T>
  3268. inline Conf_T& unsafeGetConfigByRef(Level level, std::map<Level, Conf_T>* confMap, const char* confName)
  3269. {
  3270. ELPP_UNUSED(confName);
  3271. typename std::map<Level, Conf_T>::iterator it = confMap->find(level);
  3272. if(it == confMap->end())
  3273. {
  3274. try
  3275. {
  3276. return confMap->at(Level::Global);
  3277. }
  3278. catch(...)
  3279. {
  3280. ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level ["
  3281. << LevelHelper::convertToString(level) << "]"
  3282. << std::endl << "Please ensure you have properly configured logger.", false);
  3283. }
  3284. }
  3285. return it->second;
  3286. }
  3287. template <typename Conf_T>
  3288. void setValue(Level level, const Conf_T& value, std::map<Level, Conf_T>* confMap, bool includeGlobalLevel = true)
  3289. {
  3290. // If map is empty and we are allowed to add into generic level (Level::Global), do it!
  3291. if(confMap->empty() && includeGlobalLevel)
  3292. {
  3293. confMap->insert(std::make_pair(Level::Global, value));
  3294. return;
  3295. }
  3296. // If same value exist in generic level already, dont add it to explicit level
  3297. typename std::map<Level, Conf_T>::iterator it = confMap->find(Level::Global);
  3298. if(it != confMap->end() && it->second == value)
  3299. {
  3300. return;
  3301. }
  3302. // Now make sure we dont double up values if we really need to add it to explicit level
  3303. it = confMap->find(level);
  3304. if(it == confMap->end())
  3305. {
  3306. // Value not found for level, add new
  3307. confMap->insert(std::make_pair(level, value));
  3308. }
  3309. else
  3310. {
  3311. // Value found, just update value
  3312. confMap->at(level) = value;
  3313. }
  3314. }
  3315. void build(Configurations* configurations)
  3316. {
  3317. base::threading::ScopedLock scopedLock(lock());
  3318. auto getBool = [](std::string boolStr) -> bool
  3319. { // Pass by value for trimming
  3320. base::utils::Str::trim(boolStr);
  3321. return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1");
  3322. };
  3323. std::vector<Configuration*> withFileSizeLimit;
  3324. for(Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it)
  3325. {
  3326. Configuration* conf = *it;
  3327. // We cannot use switch on strong enums because Intel C++ dont support them yet
  3328. if(conf->configurationType() == ConfigurationType::Enabled)
  3329. {
  3330. setValue(conf->level(), getBool(conf->value()), &m_enabledMap);
  3331. }
  3332. else if(conf->configurationType() == ConfigurationType::ToFile)
  3333. {
  3334. setValue(conf->level(), getBool(conf->value()), &m_toFileMap);
  3335. }
  3336. else if(conf->configurationType() == ConfigurationType::ToStandardOutput)
  3337. {
  3338. setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap);
  3339. }
  3340. else if(conf->configurationType() == ConfigurationType::Filename)
  3341. {
  3342. // We do not yet configure filename but we will configure in another
  3343. // loop. This is because if file cannot be created, we will force ToFile
  3344. // to be false. Because configuring logger is not necessarily performance
  3345. // sensative operation, we can live with another loop; (by the way this loop
  3346. // is not very heavy either)
  3347. }
  3348. else if(conf->configurationType() == ConfigurationType::Format)
  3349. {
  3350. setValue(conf->level(), base::LogFormat(conf->level(),
  3351. base::type::string_t(conf->value().begin(), conf->value().end())), &m_logFormatMap);
  3352. }
  3353. else if(conf->configurationType() == ConfigurationType::MillisecondsWidth)
  3354. {
  3355. setValue(Level::Global,
  3356. base::MillisecondsWidth(static_cast<int>(getULong(conf->value()))), &m_millisecondsWidthMap);
  3357. }
  3358. else if(conf->configurationType() == ConfigurationType::PerformanceTracking)
  3359. {
  3360. setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap);
  3361. }
  3362. else if(conf->configurationType() == ConfigurationType::MaxLogFileSize)
  3363. {
  3364. setValue(conf->level(), static_cast<std::size_t>(getULong(conf->value())), &m_maxLogFileSizeMap);
  3365. #if !defined(ELPP_NO_DEFAULT_LOG_FILE)
  3366. withFileSizeLimit.push_back(conf);
  3367. #endif // !defined(ELPP_NO_DEFAULT_LOG_FILE)
  3368. }
  3369. else if(conf->configurationType() == ConfigurationType::LogFlushThreshold)
  3370. {
  3371. setValue(conf->level(), static_cast<std::size_t>(getULong(conf->value())), &m_logFlushThresholdMap);
  3372. }
  3373. }
  3374. // As mentioned early, we will now set filename configuration in separate loop to deal with non-existent files
  3375. for(Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it)
  3376. {
  3377. Configuration* conf = *it;
  3378. if(conf->configurationType() == ConfigurationType::Filename)
  3379. {
  3380. insertFile(conf->level(), conf->value());
  3381. }
  3382. }
  3383. for(std::vector<Configuration*>::iterator conf = withFileSizeLimit.begin();
  3384. conf != withFileSizeLimit.end(); ++conf)
  3385. {
  3386. // This is not unsafe as mutex is locked in currect scope
  3387. unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback);
  3388. }
  3389. }
  3390. unsigned long getULong(std::string confVal)
  3391. {
  3392. bool valid = true;
  3393. base::utils::Str::trim(confVal);
  3394. valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(),
  3395. [](char c)
  3396. {
  3397. return !base::utils::Str::isDigit(c);
  3398. }) == confVal.end();
  3399. if(!valid)
  3400. {
  3401. valid = false;
  3402. ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]");
  3403. return 0;
  3404. }
  3405. return atol(confVal.c_str());
  3406. }
  3407. std::string resolveFilename(const std::string& filename)
  3408. {
  3409. std::string resultingFilename = filename;
  3410. std::size_t dateIndex = std::string::npos;
  3411. std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename);
  3412. if((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos)
  3413. {
  3414. while(dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar)
  3415. {
  3416. dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1);
  3417. }
  3418. if(dateIndex != std::string::npos)
  3419. {
  3420. const char* ptr = resultingFilename.c_str() + dateIndex;
  3421. // Goto end of specifier
  3422. ptr += dateTimeFormatSpecifierStr.size();
  3423. std::string fmt;
  3424. if((resultingFilename.size() > dateIndex) && (ptr[0] == '{'))
  3425. {
  3426. // User has provided format for date/time
  3427. ++ptr;
  3428. int count = 1; // Start by 1 in order to remove starting brace
  3429. std::stringstream ss;
  3430. for(; *ptr; ++ptr, ++count)
  3431. {
  3432. if(*ptr == '}')
  3433. {
  3434. ++count; // In order to remove ending brace
  3435. break;
  3436. }
  3437. ss << *ptr;
  3438. }
  3439. resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count);
  3440. fmt = ss.str();
  3441. }
  3442. else
  3443. {
  3444. fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename);
  3445. }
  3446. base::MillisecondsWidth msWidth(3);
  3447. std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &msWidth);
  3448. base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename
  3449. base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now);
  3450. }
  3451. }
  3452. /////////add for same direct oneday/////////////////////
  3453. base::MillisecondsWidth msWidth(3);
  3454. std::string now = base::utils::DateTime::getDateTime("%Y%M%d_%H%m%s", &msWidth);
  3455. base::utils::Str::replaceAll(now, '/', '-');
  3456. base::utils::Str::replaceAll(resultingFilename, "filename{%Y%M%d_%H%m%s}", now);
  3457. /////////////////////////////// ///////////////////////
  3458. return resultingFilename;
  3459. }
  3460. void insertFile(Level level, const std::string& fullFilename)
  3461. {
  3462. std::string resolvedFilename = resolveFilename(fullFilename);
  3463. if(resolvedFilename.empty())
  3464. {
  3465. std::cerr << "Could not load empty file for logging, please re-check your configurations for level ["
  3466. << LevelHelper::convertToString(level) << "]";
  3467. }
  3468. std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeperator);
  3469. if(filePath.size() < resolvedFilename.size())
  3470. {
  3471. base::utils::File::createPath(filePath);
  3472. }
  3473. auto create = [&](Level level)
  3474. {
  3475. base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename);
  3476. base::type::fstream_t* fs = nullptr;
  3477. if(filestreamIter == m_logStreamsReference->end())
  3478. {
  3479. // We need a completely new stream, nothing to share with
  3480. fs = base::utils::File::newFileStream(resolvedFilename);
  3481. m_filenameMap.insert(std::make_pair(level, resolvedFilename));
  3482. m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs)));
  3483. m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level))));
  3484. }
  3485. else
  3486. {
  3487. // Woops! we have an existing one, share it!
  3488. m_filenameMap.insert(std::make_pair(level, filestreamIter->first));
  3489. m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second)));
  3490. fs = filestreamIter->second.get();
  3491. }
  3492. if(fs == nullptr)
  3493. {
  3494. // We display bad file error from newFileStream()
  3495. ELPP_INTERNAL_ERROR("Setting [TO_FILE] of ["
  3496. << LevelHelper::convertToString(level) << "] to FALSE", false);
  3497. setValue(level, false, &m_toFileMap);
  3498. }
  3499. };
  3500. // If we dont have file conf for any level, create it for Level::Global first
  3501. // otherwise create for specified level
  3502. create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level);
  3503. struct ::tm timeinfo = base::utils::DateTime::getCurrentTm();
  3504. m_fileFullnameMap[level] = fullFilename;
  3505. m_fileLastTimeMap[level] = timeinfo.tm_hour;
  3506. }
  3507. bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback)
  3508. {
  3509. base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get();
  3510. if(fs == nullptr)
  3511. {
  3512. return true;
  3513. }
  3514. std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize");
  3515. /*std::size_t*/ int64_t currFileSize = base::utils::File::getSizeOfFile(fs);
  3516. if(maxLogFileSize != 0 && currFileSize >= (int64_t)maxLogFileSize)
  3517. {
  3518. std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename");
  3519. ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level ["
  3520. << LevelHelper::convertToString(level) << "]");
  3521. fs->close();
  3522. PreRollOutCallback(fname.c_str(), currFileSize);
  3523. fs->open(fname, std::fstream::out | std::fstream::trunc);
  3524. return true;
  3525. }
  3526. struct ::tm timeinfo = base::utils::DateTime::getCurrentTm();
  3527. std::size_t lastRollingHour = unsafeGetConfigByRef(level, &m_fileLastTimeMap, "lastRollingTime");
  3528. if(lastRollingHour != (std::size_t)timeinfo.tm_hour)
  3529. {
  3530. ////std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename");
  3531. ////fs->close();
  3532. ////std::string& fullFileName = unsafeGetConfigByRef(level, &m_fileFullnameMap, "fileFullName");
  3533. ////std::string resolvedFilename = resolveFilename(fullFileName);
  3534. ////if (resolvedFilename.empty()) {
  3535. //// std::cerr << "Could not load empty file for logging, please re-check your configurations for level ["
  3536. //// << LevelHelper::convertToString(level) << "]";
  3537. //// return false;
  3538. ////}
  3539. ////m_filenameMap[level] = resolvedFilename;
  3540. ////fs->open(fname, std::fstream::out | std::fstream::trunc);
  3541. ////return true;
  3542. std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename");
  3543. fs->close();
  3544. //base::utils::safeDelete(fs);
  3545. m_fileStreamMap.erase(level);
  3546. m_filenameMap.erase(level);
  3547. m_logStreamsReference->erase(fname);
  3548. //PreRollOutCallback(fname.c_str(), currFileSize);
  3549. std::string& fileFullname = unsafeGetConfigByRef(level, &m_fileFullnameMap, "fileFullName");
  3550. insertFile(level, fileFullname);
  3551. return true;
  3552. //// check
  3553. //fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename");
  3554. //base::type::fstream_t* new_fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get();
  3555. //if (new_fs == nullptr) {
  3556. // return true;
  3557. //}
  3558. //if (new_fs->is_open())
  3559. //{
  3560. // // just check
  3561. // return true;
  3562. //}
  3563. //new_fs->open(fname, std::fstream::out | std::fstream::trunc);
  3564. //return true;
  3565. }
  3566. return false;
  3567. }
  3568. bool validateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback)
  3569. {
  3570. base::threading::ScopedLock scopedLock(lock());
  3571. return unsafeValidateFileRolling(level, PreRollOutCallback);
  3572. }
  3573. };
  3574. /// @brief Class that keeps record of current line hit for occasional logging
  3575. class HitCounter
  3576. {
  3577. public:
  3578. HitCounter(void) :
  3579. m_filename(""),
  3580. m_lineNumber(0),
  3581. m_hitCounts(0)
  3582. {
  3583. }
  3584. HitCounter(const char* filename, unsigned long int lineNumber) :
  3585. m_filename(filename),
  3586. m_lineNumber(lineNumber),
  3587. m_hitCounts(0)
  3588. {
  3589. }
  3590. HitCounter(const HitCounter& hitCounter) :
  3591. m_filename(hitCounter.m_filename),
  3592. m_lineNumber(hitCounter.m_lineNumber),
  3593. m_hitCounts(hitCounter.m_hitCounts)
  3594. {
  3595. }
  3596. HitCounter& operator=(const HitCounter& hitCounter)
  3597. {
  3598. m_filename = hitCounter.m_filename;
  3599. m_lineNumber = hitCounter.m_lineNumber;
  3600. m_hitCounts = hitCounter.m_hitCounts;
  3601. return *this;
  3602. }
  3603. virtual ~HitCounter(void)
  3604. {
  3605. }
  3606. /// @brief Resets location of current hit counter
  3607. inline void resetLocation(const char* filename, unsigned long int lineNumber)
  3608. {
  3609. m_filename = filename;
  3610. m_lineNumber = lineNumber;
  3611. }
  3612. /// @brief Validates hit counts and resets it if necessary
  3613. inline void validateHitCounts(std::size_t n)
  3614. {
  3615. if(m_hitCounts >= base::consts::kMaxLogPerCounter)
  3616. {
  3617. m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0);
  3618. }
  3619. ++m_hitCounts;
  3620. }
  3621. inline const char* filename(void) const
  3622. {
  3623. return m_filename;
  3624. }
  3625. inline unsigned long int lineNumber(void) const
  3626. {
  3627. return m_lineNumber;
  3628. }
  3629. inline std::size_t hitCounts(void) const
  3630. {
  3631. return m_hitCounts;
  3632. }
  3633. inline void increment(void)
  3634. {
  3635. ++m_hitCounts;
  3636. }
  3637. class Predicate
  3638. {
  3639. public:
  3640. Predicate(const char* filename, unsigned long int lineNumber)
  3641. : m_filename(filename),
  3642. m_lineNumber(lineNumber)
  3643. {
  3644. }
  3645. inline bool operator()(const HitCounter* counter)
  3646. {
  3647. return ((counter != nullptr) &&
  3648. (strcmp(counter->m_filename, m_filename) == 0) &&
  3649. (counter->m_lineNumber == m_lineNumber));
  3650. }
  3651. private:
  3652. const char* m_filename;
  3653. unsigned long int m_lineNumber;
  3654. };
  3655. private:
  3656. const char* m_filename;
  3657. unsigned long int m_lineNumber;
  3658. std::size_t m_hitCounts;
  3659. };
  3660. /// @brief Repository for hit counters used across the application
  3661. class RegisteredHitCounters : public base::utils::RegistryWithPred<base::HitCounter, base::HitCounter::Predicate>
  3662. {
  3663. public:
  3664. /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one
  3665. /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned
  3666. bool validateEveryN(const char* filename, unsigned long int lineNumber, std::size_t n)
  3667. {
  3668. base::threading::ScopedLock scopedLock(lock());
  3669. base::HitCounter* counter = get(filename, lineNumber);
  3670. if(counter == nullptr)
  3671. {
  3672. registerNew(counter = new base::HitCounter(filename, lineNumber));
  3673. }
  3674. counter->validateHitCounts(n);
  3675. bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0);
  3676. return result;
  3677. }
  3678. /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one
  3679. /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned
  3680. bool validateAfterN(const char* filename, unsigned long int lineNumber, std::size_t n)
  3681. {
  3682. base::threading::ScopedLock scopedLock(lock());
  3683. base::HitCounter* counter = get(filename, lineNumber);
  3684. if(counter == nullptr)
  3685. {
  3686. registerNew(counter = new base::HitCounter(filename, lineNumber));
  3687. }
  3688. // Do not use validateHitCounts here since we do not want to reset counter here
  3689. // Note the >= instead of > because we are incrementing
  3690. // after this check
  3691. if(counter->hitCounts() >= n)
  3692. return true;
  3693. counter->increment();
  3694. return false;
  3695. }
  3696. /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one
  3697. /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned
  3698. bool validateNTimes(const char* filename, unsigned long int lineNumber, std::size_t n)
  3699. {
  3700. base::threading::ScopedLock scopedLock(lock());
  3701. base::HitCounter* counter = get(filename, lineNumber);
  3702. if(counter == nullptr)
  3703. {
  3704. registerNew(counter = new base::HitCounter(filename, lineNumber));
  3705. }
  3706. counter->increment();
  3707. // Do not use validateHitCounts here since we do not want to reset counter here
  3708. if(counter->hitCounts() <= n)
  3709. return true;
  3710. return false;
  3711. }
  3712. /// @brief Gets hit counter registered at specified position
  3713. inline const base::HitCounter* getCounter(const char* filename, unsigned long int lineNumber)
  3714. {
  3715. base::threading::ScopedLock scopedLock(lock());
  3716. return get(filename, lineNumber);
  3717. }
  3718. };
  3719. /// @brief Action to be taken for dispatching
  3720. enum class DispatchAction : base::type::EnumType
  3721. {
  3722. None = 1, NormalLog = 2, SysLog = 4
  3723. };
  3724. } // namespace base
  3725. template <typename T>
  3726. class Callback : protected base::threading::ThreadSafe
  3727. {
  3728. public:
  3729. Callback(void) : m_enabled(true)
  3730. {
  3731. }
  3732. inline bool enabled(void) const
  3733. {
  3734. return m_enabled;
  3735. }
  3736. inline void setEnabled(bool enabled)
  3737. {
  3738. base::threading::ScopedLock scopedLock(lock());
  3739. m_enabled = enabled;
  3740. }
  3741. protected:
  3742. virtual void handle(const T* handlePtr) = 0;
  3743. private:
  3744. bool m_enabled;
  3745. };
  3746. class LogDispatchData
  3747. {
  3748. public:
  3749. LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None)
  3750. {
  3751. }
  3752. inline const LogMessage* logMessage(void) const
  3753. {
  3754. return m_logMessage;
  3755. }
  3756. inline base::DispatchAction dispatchAction(void) const
  3757. {
  3758. return m_dispatchAction;
  3759. }
  3760. private:
  3761. LogMessage* m_logMessage;
  3762. base::DispatchAction m_dispatchAction;
  3763. friend class base::LogDispatcher;
  3764. inline void setLogMessage(LogMessage* logMessage)
  3765. {
  3766. m_logMessage = logMessage;
  3767. }
  3768. inline void setDispatchAction(base::DispatchAction dispatchAction)
  3769. {
  3770. m_dispatchAction = dispatchAction;
  3771. }
  3772. };
  3773. class LogDispatchCallback : public Callback<LogDispatchData>
  3774. {
  3775. private:
  3776. friend class base::LogDispatcher;
  3777. };
  3778. class PerformanceTrackingCallback : public Callback<PerformanceTrackingData>
  3779. {
  3780. private:
  3781. friend class base::PerformanceTracker;
  3782. };
  3783. class LogBuilder : base::NoCopy
  3784. {
  3785. public:
  3786. virtual ~LogBuilder(void)
  3787. {
  3788. ELPP_INTERNAL_INFO(3, "Destroying log builder...")
  3789. }
  3790. virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0;
  3791. void convertToColoredOutput(base::type::string_t* logLine, Level level)
  3792. {
  3793. if(!base::utils::s_termSupportsColor) return;
  3794. const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m");
  3795. if(level == Level::Error || level == Level::Fatal)
  3796. *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor;
  3797. else if(level == Level::Warning)
  3798. *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor;
  3799. }
  3800. private:
  3801. friend class el::base::DefaultLogDispatchCallback;
  3802. };
  3803. typedef std::shared_ptr<LogBuilder> LogBuilderPtr;
  3804. /// @brief Represents a logger holding ID and configurations we need to write logs
  3805. ///
  3806. /// @detail This class does not write logs itself instead its used by writer to read configuations from.
  3807. class Logger : public base::threading::ThreadSafe, public Loggable
  3808. {
  3809. public:
  3810. Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference) :
  3811. m_id(id),
  3812. m_typedConfigurations(nullptr),
  3813. m_parentApplicationName(std::string()),
  3814. m_isConfigured(false),
  3815. m_logStreamsReference(logStreamsReference)
  3816. {
  3817. initUnflushedCount();
  3818. }
  3819. Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMap* logStreamsReference) :
  3820. m_id(id),
  3821. m_typedConfigurations(nullptr),
  3822. m_parentApplicationName(std::string()),
  3823. m_isConfigured(false),
  3824. m_logStreamsReference(logStreamsReference)
  3825. {
  3826. initUnflushedCount();
  3827. configure(configurations);
  3828. }
  3829. Logger(const Logger& logger)
  3830. {
  3831. base::utils::safeDelete(m_typedConfigurations);
  3832. m_id = logger.m_id;
  3833. m_typedConfigurations = logger.m_typedConfigurations;
  3834. m_parentApplicationName = logger.m_parentApplicationName;
  3835. m_isConfigured = logger.m_isConfigured;
  3836. m_configurations = logger.m_configurations;
  3837. m_unflushedCount = logger.m_unflushedCount;
  3838. m_logStreamsReference = logger.m_logStreamsReference;
  3839. }
  3840. Logger& operator=(const Logger& logger)
  3841. {
  3842. base::utils::safeDelete(m_typedConfigurations);
  3843. m_id = logger.m_id;
  3844. m_typedConfigurations = logger.m_typedConfigurations;
  3845. m_parentApplicationName = logger.m_parentApplicationName;
  3846. m_isConfigured = logger.m_isConfigured;
  3847. m_configurations = logger.m_configurations;
  3848. m_unflushedCount = logger.m_unflushedCount;
  3849. m_logStreamsReference = logger.m_logStreamsReference;
  3850. return *this;
  3851. }
  3852. virtual ~Logger(void)
  3853. {
  3854. base::utils::safeDelete(m_typedConfigurations);
  3855. }
  3856. virtual inline void log(el::base::type::ostream_t& os) const
  3857. {
  3858. os << m_id.c_str();
  3859. }
  3860. /// @brief Configures the logger using specified configurations.
  3861. void configure(const Configurations& configurations)
  3862. {
  3863. m_isConfigured = false; // we set it to false in case if we fail
  3864. initUnflushedCount();
  3865. if(m_typedConfigurations != nullptr)
  3866. {
  3867. Configurations* c = const_cast<Configurations*>(m_typedConfigurations->configurations());
  3868. if(c->hasConfiguration(Level::Global, ConfigurationType::Filename))
  3869. {
  3870. // This check is definitely needed for cases like ELPP_NO_DEFAULT_LOG_FILE
  3871. flush();
  3872. }
  3873. }
  3874. base::threading::ScopedLock scopedLock(lock());
  3875. if(m_configurations != configurations)
  3876. {
  3877. m_configurations.setFromBase(const_cast<Configurations*>(&configurations));
  3878. }
  3879. base::utils::safeDelete(m_typedConfigurations);
  3880. m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference);
  3881. resolveLoggerFormatSpec();
  3882. m_isConfigured = true;
  3883. }
  3884. /// @brief Reconfigures logger using existing configurations
  3885. inline void reconfigure(void)
  3886. {
  3887. ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]");
  3888. configure(m_configurations);
  3889. }
  3890. inline const std::string& id(void) const
  3891. {
  3892. return m_id;
  3893. }
  3894. inline const std::string& parentApplicationName(void) const
  3895. {
  3896. return m_parentApplicationName;
  3897. }
  3898. inline void setParentApplicationName(const std::string& parentApplicationName)
  3899. {
  3900. m_parentApplicationName = parentApplicationName;
  3901. }
  3902. inline Configurations* configurations(void)
  3903. {
  3904. return &m_configurations;
  3905. }
  3906. inline base::TypedConfigurations* typedConfigurations(void)
  3907. {
  3908. return m_typedConfigurations;
  3909. }
  3910. static inline bool isValidId(const std::string& id)
  3911. {
  3912. for(std::string::const_iterator it = id.begin(); it != id.end(); ++it)
  3913. {
  3914. if(!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it))
  3915. {
  3916. return false;
  3917. }
  3918. }
  3919. return true;
  3920. }
  3921. /// @brief Flushes logger to sync all log files for all levels
  3922. inline void flush(void)
  3923. {
  3924. ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels");
  3925. base::threading::ScopedLock scopedLock(lock());
  3926. base::type::EnumType lIndex = LevelHelper::kMinValid;
  3927. LevelHelper::forEachLevel(&lIndex, [&](void) -> bool
  3928. {
  3929. flush(LevelHelper::castFromInt(lIndex), nullptr);
  3930. return false;
  3931. });
  3932. }
  3933. inline void flush(Level level, base::type::fstream_t* fs)
  3934. {
  3935. if(fs == nullptr && m_typedConfigurations->toFile(level))
  3936. {
  3937. fs = m_typedConfigurations->fileStream(level);
  3938. }
  3939. if(fs != nullptr)
  3940. {
  3941. fs->flush();
  3942. m_unflushedCount.find(level)->second = 0;
  3943. }
  3944. }
  3945. inline bool isFlushNeeded(Level level)
  3946. {
  3947. return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level);
  3948. }
  3949. inline LogBuilder* logBuilder(void) const
  3950. {
  3951. return m_logBuilder.get();
  3952. }
  3953. inline void setLogBuilder(const LogBuilderPtr& logBuilder)
  3954. {
  3955. m_logBuilder = logBuilder;
  3956. }
  3957. inline bool enabled(Level level) const
  3958. {
  3959. return m_typedConfigurations->enabled(level);
  3960. }
  3961. #if ELPP_VARIADIC_TEMPLATES_SUPPORTED
  3962. # define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\
  3963. template <typename T, typename... Args>\
  3964. inline void FUNCTION_NAME(const char*, const T&, const Args&...);\
  3965. template <typename T>\
  3966. inline void FUNCTION_NAME(const T&);
  3967. template <typename T, typename... Args>
  3968. inline void verbose(int, const char*, const T&, const Args&...);
  3969. template <typename T>
  3970. inline void verbose(int, const T&);
  3971. LOGGER_LEVEL_WRITERS_SIGNATURES(info)
  3972. LOGGER_LEVEL_WRITERS_SIGNATURES(debug)
  3973. LOGGER_LEVEL_WRITERS_SIGNATURES(warn)
  3974. LOGGER_LEVEL_WRITERS_SIGNATURES(error)
  3975. LOGGER_LEVEL_WRITERS_SIGNATURES(fatal)
  3976. LOGGER_LEVEL_WRITERS_SIGNATURES(trace)
  3977. # undef LOGGER_LEVEL_WRITERS_SIGNATURES
  3978. #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED
  3979. private:
  3980. std::string m_id;
  3981. base::TypedConfigurations* m_typedConfigurations;
  3982. base::type::stringstream_t m_stream;
  3983. std::string m_parentApplicationName;
  3984. bool m_isConfigured;
  3985. Configurations m_configurations;
  3986. std::map<Level, unsigned int> m_unflushedCount;
  3987. base::LogStreamsReferenceMap* m_logStreamsReference;
  3988. LogBuilderPtr m_logBuilder;
  3989. friend class el::LogMessage;
  3990. friend class el::Loggers;
  3991. friend class el::Helpers;
  3992. friend class el::base::RegisteredLoggers;
  3993. friend class el::base::DefaultLogDispatchCallback;
  3994. friend class el::base::MessageBuilder;
  3995. friend class el::base::Writer;
  3996. friend class el::base::PErrorWriter;
  3997. friend class el::base::Storage;
  3998. friend class el::base::PerformanceTracker;
  3999. friend class el::base::LogDispatcher;
  4000. Logger(void);
  4001. #if ELPP_VARIADIC_TEMPLATES_SUPPORTED
  4002. template <typename T, typename... Args>
  4003. void log_(Level, int, const char*, const T&, const Args&...);
  4004. template <typename T>
  4005. inline void log_(Level, int, const T&);
  4006. template <typename T, typename... Args>
  4007. void log(Level, const char*, const T&, const Args&...);
  4008. template <typename T>
  4009. inline void log(Level, const T&);
  4010. #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED
  4011. void initUnflushedCount(void)
  4012. {
  4013. m_unflushedCount.clear();
  4014. base::type::EnumType lIndex = LevelHelper::kMinValid;
  4015. LevelHelper::forEachLevel(&lIndex, [&](void) -> bool
  4016. {
  4017. m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0));
  4018. return false;
  4019. });
  4020. }
  4021. inline base::type::stringstream_t& stream(void)
  4022. {
  4023. return m_stream;
  4024. }
  4025. void resolveLoggerFormatSpec(void) const
  4026. {
  4027. base::type::EnumType lIndex = LevelHelper::kMinValid;
  4028. LevelHelper::forEachLevel(&lIndex, [&](void) -> bool
  4029. {
  4030. base::LogFormat* logFormat =
  4031. const_cast<base::LogFormat*>(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex)));
  4032. base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id);
  4033. return false;
  4034. });
  4035. }
  4036. };
  4037. namespace base {
  4038. /// @brief Loggers repository
  4039. class RegisteredLoggers : public base::utils::Registry<Logger, std::string>
  4040. {
  4041. public:
  4042. explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder) :
  4043. m_defaultLogBuilder(defaultLogBuilder)
  4044. {
  4045. m_defaultConfigurations.setToDefault();
  4046. }
  4047. virtual ~RegisteredLoggers(void)
  4048. {
  4049. flushAll();
  4050. }
  4051. inline void setDefaultConfigurations(const Configurations& configurations)
  4052. {
  4053. base::threading::ScopedLock scopedLock(lock());
  4054. m_defaultConfigurations.setFromBase(const_cast<Configurations*>(&configurations));
  4055. }
  4056. inline Configurations* defaultConfigurations(void)
  4057. {
  4058. return &m_defaultConfigurations;
  4059. }
  4060. Logger* get(const std::string& id, bool forceCreation = true)
  4061. {
  4062. base::threading::ScopedLock scopedLock(lock());
  4063. Logger* logger_ = base::utils::Registry<Logger, std::string>::get(id);
  4064. if(logger_ == nullptr && forceCreation)
  4065. {
  4066. bool validId = Logger::isValidId(id);
  4067. if(!validId)
  4068. {
  4069. ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger.");
  4070. return nullptr;
  4071. }
  4072. logger_ = new Logger(id, m_defaultConfigurations, &m_logStreamsReference);
  4073. logger_->m_logBuilder = m_defaultLogBuilder;
  4074. registerNew(id, logger_);
  4075. }
  4076. return logger_;
  4077. }
  4078. bool remove(const std::string& id)
  4079. {
  4080. if(id == "default")
  4081. {
  4082. return false;
  4083. }
  4084. Logger* logger = base::utils::Registry<Logger, std::string>::get(id);
  4085. if(logger != nullptr)
  4086. {
  4087. unregister(logger);
  4088. }
  4089. return true;
  4090. }
  4091. inline bool has(const std::string& id)
  4092. {
  4093. return get(id, false) != nullptr;
  4094. }
  4095. inline void unregister(Logger*& logger)
  4096. {
  4097. base::threading::ScopedLock scopedLock(lock());
  4098. base::utils::Registry<Logger, std::string>::unregister(logger->id());
  4099. }
  4100. inline base::LogStreamsReferenceMap* logStreamsReference(void)
  4101. {
  4102. return &m_logStreamsReference;
  4103. }
  4104. inline void flushAll(void)
  4105. {
  4106. ELPP_INTERNAL_INFO(1, "Flushing all log files");
  4107. base::threading::ScopedLock scopedLock(lock());
  4108. for(base::LogStreamsReferenceMap::iterator it = m_logStreamsReference.begin();
  4109. it != m_logStreamsReference.end(); ++it)
  4110. {
  4111. if(it->second.get() == nullptr) continue;
  4112. it->second->flush();
  4113. }
  4114. }
  4115. private:
  4116. LogBuilderPtr m_defaultLogBuilder;
  4117. Configurations m_defaultConfigurations;
  4118. base::LogStreamsReferenceMap m_logStreamsReference;
  4119. friend class el::base::Storage;
  4120. };
  4121. /// @brief Represents registries for verbose logging
  4122. class VRegistry : base::NoCopy, public base::threading::ThreadSafe
  4123. {
  4124. public:
  4125. explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags) : m_level(level), m_pFlags(pFlags)
  4126. {
  4127. }
  4128. /// @brief Sets verbose level. Accepted range is 0-9
  4129. inline void setLevel(base::type::VerboseLevel level)
  4130. {
  4131. base::threading::ScopedLock scopedLock(lock());
  4132. if(level < 0)
  4133. m_level = 0;
  4134. else if(level > 9)
  4135. m_level = base::consts::kMaxVerboseLevel;
  4136. else
  4137. m_level = level;
  4138. }
  4139. inline base::type::VerboseLevel level(void) const
  4140. {
  4141. return m_level;
  4142. }
  4143. inline void clearModules(void)
  4144. {
  4145. base::threading::ScopedLock scopedLock(lock());
  4146. m_modules.clear();
  4147. }
  4148. void setModules(const char* modules)
  4149. {
  4150. base::threading::ScopedLock scopedLock(lock());
  4151. auto addSuffix = [](std::stringstream& ss, const char* sfx, const char* prev)
  4152. {
  4153. if(prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev)))
  4154. {
  4155. std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev)));
  4156. ss.str(std::string(""));
  4157. ss << chr;
  4158. }
  4159. if(base::utils::Str::endsWith(ss.str(), std::string(sfx)))
  4160. {
  4161. std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx)));
  4162. ss.str(std::string(""));
  4163. ss << chr;
  4164. }
  4165. ss << sfx;
  4166. };
  4167. auto insert = [&](std::stringstream& ss, base::type::VerboseLevel level)
  4168. {
  4169. if(!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags))
  4170. {
  4171. addSuffix(ss, ".h", nullptr);
  4172. m_modules.insert(std::make_pair(ss.str(), level));
  4173. addSuffix(ss, ".c", ".h");
  4174. m_modules.insert(std::make_pair(ss.str(), level));
  4175. addSuffix(ss, ".cpp", ".c");
  4176. m_modules.insert(std::make_pair(ss.str(), level));
  4177. addSuffix(ss, ".cc", ".cpp");
  4178. m_modules.insert(std::make_pair(ss.str(), level));
  4179. addSuffix(ss, ".cxx", ".cc");
  4180. m_modules.insert(std::make_pair(ss.str(), level));
  4181. addSuffix(ss, ".-inl.h", ".cxx");
  4182. m_modules.insert(std::make_pair(ss.str(), level));
  4183. addSuffix(ss, ".hxx", ".-inl.h");
  4184. m_modules.insert(std::make_pair(ss.str(), level));
  4185. addSuffix(ss, ".hpp", ".hxx");
  4186. m_modules.insert(std::make_pair(ss.str(), level));
  4187. addSuffix(ss, ".hh", ".hpp");
  4188. }
  4189. m_modules.insert(std::make_pair(ss.str(), level));
  4190. };
  4191. bool isMod = true;
  4192. bool isLevel = false;
  4193. std::stringstream ss;
  4194. int level = -1;
  4195. for(; *modules; ++modules)
  4196. {
  4197. switch(*modules)
  4198. {
  4199. case '=':
  4200. isLevel = true;
  4201. isMod = false;
  4202. break;
  4203. case ',':
  4204. isLevel = false;
  4205. isMod = true;
  4206. if(!ss.str().empty() && level != -1)
  4207. {
  4208. insert(ss, level);
  4209. ss.str(std::string(""));
  4210. level = -1;
  4211. }
  4212. break;
  4213. default:
  4214. if(isMod)
  4215. {
  4216. ss << *modules;
  4217. }
  4218. else if(isLevel)
  4219. {
  4220. if(isdigit(*modules))
  4221. {
  4222. level = static_cast<base::type::VerboseLevel>(*modules) - 48;
  4223. }
  4224. }
  4225. break;
  4226. }
  4227. }
  4228. if(!ss.str().empty() && level != -1)
  4229. {
  4230. insert(ss, level);
  4231. }
  4232. }
  4233. bool allowed(base::type::VerboseLevel vlevel, const char* file)
  4234. {
  4235. base::threading::ScopedLock scopedLock(lock());
  4236. if(m_modules.empty() || file == nullptr)
  4237. {
  4238. return vlevel <= m_level;
  4239. }
  4240. else
  4241. {
  4242. std::map<std::string, base::type::VerboseLevel>::iterator it = m_modules.begin();
  4243. for(; it != m_modules.end(); ++it)
  4244. {
  4245. if(base::utils::Str::wildCardMatch(file, it->first.c_str()))
  4246. {
  4247. return vlevel <= it->second;
  4248. }
  4249. }
  4250. if(base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags))
  4251. {
  4252. return true;
  4253. }
  4254. return false;
  4255. }
  4256. }
  4257. inline const std::map<std::string, base::type::VerboseLevel>& modules(void) const
  4258. {
  4259. return m_modules;
  4260. }
  4261. void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs)
  4262. {
  4263. if(commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") ||
  4264. commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE"))
  4265. {
  4266. setLevel(base::consts::kMaxVerboseLevel);
  4267. }
  4268. else if(commandLineArgs->hasParamWithValue("--v"))
  4269. {
  4270. setLevel(atoi(commandLineArgs->getParamValue("--v")));
  4271. }
  4272. else if(commandLineArgs->hasParamWithValue("--V"))
  4273. {
  4274. setLevel(atoi(commandLineArgs->getParamValue("--V")));
  4275. }
  4276. else if((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled())
  4277. {
  4278. setModules(commandLineArgs->getParamValue("-vmodule"));
  4279. }
  4280. else if(commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled())
  4281. {
  4282. setModules(commandLineArgs->getParamValue("-VMODULE"));
  4283. }
  4284. }
  4285. /// @brief Whether or not vModules enabled
  4286. inline bool vModulesEnabled(void)
  4287. {
  4288. return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags);
  4289. }
  4290. private:
  4291. base::type::VerboseLevel m_level;
  4292. base::type::EnumType* m_pFlags;
  4293. std::map<std::string, base::type::VerboseLevel> m_modules;
  4294. };
  4295. } // namespace base
  4296. class LogMessage
  4297. {
  4298. public:
  4299. LogMessage(Level level, const std::string& file, unsigned long int line, const std::string& func,
  4300. base::type::VerboseLevel verboseLevel, Logger* logger) :
  4301. m_level(level), m_file(file), m_line(line), m_func(func),
  4302. m_verboseLevel(verboseLevel), m_logger(logger), m_message(std::move(logger->stream().str()))
  4303. {
  4304. }
  4305. inline Level level(void) const
  4306. {
  4307. return m_level;
  4308. }
  4309. inline const std::string& file(void) const
  4310. {
  4311. return m_file;
  4312. }
  4313. inline unsigned long int line(void) const
  4314. {
  4315. return m_line;
  4316. } // NOLINT
  4317. inline const std::string& func(void) const
  4318. {
  4319. return m_func;
  4320. }
  4321. inline base::type::VerboseLevel verboseLevel(void) const
  4322. {
  4323. return m_verboseLevel;
  4324. }
  4325. inline Logger* logger(void) const
  4326. {
  4327. return m_logger;
  4328. }
  4329. inline const base::type::string_t& message(void) const
  4330. {
  4331. return m_message;
  4332. }
  4333. private:
  4334. Level m_level;
  4335. std::string m_file;
  4336. unsigned long int m_line;
  4337. std::string m_func;
  4338. base::type::VerboseLevel m_verboseLevel;
  4339. Logger* m_logger;
  4340. base::type::string_t m_message;
  4341. };
  4342. namespace base {
  4343. #if ELPP_ASYNC_LOGGING
  4344. class AsyncLogItem
  4345. {
  4346. public:
  4347. explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine)
  4348. : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine)
  4349. {
  4350. }
  4351. virtual ~AsyncLogItem()
  4352. {
  4353. }
  4354. inline LogMessage* logMessage(void)
  4355. {
  4356. return &m_logMessage;
  4357. }
  4358. inline LogDispatchData* data(void)
  4359. {
  4360. return &m_dispatchData;
  4361. }
  4362. inline base::type::string_t logLine(void)
  4363. {
  4364. return m_logLine;
  4365. }
  4366. private:
  4367. LogMessage m_logMessage;
  4368. LogDispatchData m_dispatchData;
  4369. base::type::string_t m_logLine;
  4370. };
  4371. class AsyncLogQueue : public base::threading::ThreadSafe
  4372. {
  4373. public:
  4374. virtual ~AsyncLogQueue()
  4375. {
  4376. ELPP_INTERNAL_INFO(6, "~AsyncLogQueue");
  4377. }
  4378. inline AsyncLogItem next(void)
  4379. {
  4380. base::threading::ScopedLock scopedLock(lock());
  4381. AsyncLogItem result = m_queue.front();
  4382. m_queue.pop();
  4383. return result;
  4384. }
  4385. inline void push(const AsyncLogItem& item)
  4386. {
  4387. base::threading::ScopedLock scopedLock(lock());
  4388. m_queue.push(item);
  4389. }
  4390. inline void pop(void)
  4391. {
  4392. base::threading::ScopedLock scopedLock(lock());
  4393. m_queue.pop();
  4394. }
  4395. inline AsyncLogItem front(void)
  4396. {
  4397. base::threading::ScopedLock scopedLock(lock());
  4398. return m_queue.front();
  4399. }
  4400. inline bool empty(void)
  4401. {
  4402. base::threading::ScopedLock scopedLock(lock());
  4403. return m_queue.empty();
  4404. }
  4405. private:
  4406. std::queue<AsyncLogItem> m_queue;
  4407. };
  4408. class IWorker
  4409. {
  4410. public:
  4411. virtual ~IWorker()
  4412. {
  4413. }
  4414. virtual void start() = 0;
  4415. };
  4416. #endif // ELPP_ASYNC_LOGGING
  4417. /// @brief Easylogging++ management storage
  4418. class Storage : base::NoCopy, public base::threading::ThreadSafe
  4419. {
  4420. public:
  4421. #if ELPP_ASYNC_LOGGING
  4422. Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) :
  4423. #else
  4424. explicit Storage(const LogBuilderPtr& defaultLogBuilder) :
  4425. #endif // ELPP_ASYNC_LOGGING
  4426. m_registeredHitCounters(new base::RegisteredHitCounters()),
  4427. m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)),
  4428. m_flags(0x0),
  4429. m_vRegistry(new base::VRegistry(0, &m_flags)),
  4430. #if ELPP_ASYNC_LOGGING
  4431. m_asyncLogQueue(new base::AsyncLogQueue()),
  4432. m_asyncDispatchWorker(asyncDispatchWorker),
  4433. #endif // ELPP_ASYNC_LOGGING
  4434. m_preRollOutCallback(base::defaultPreRollOutCallback)
  4435. {
  4436. // Register default logger
  4437. m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId));
  4438. // Register performance logger and reconfigure format
  4439. Logger* performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId));
  4440. performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg"));
  4441. performanceLogger->reconfigure();
  4442. #if defined(ELPP_SYSLOG)
  4443. // Register syslog logger and reconfigure format
  4444. Logger* sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId));
  4445. sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg"));
  4446. sysLogLogger->reconfigure();
  4447. #else
  4448. ELPP_UNUSED(base::consts::kSysLogLoggerId);
  4449. #endif // defined(ELPP_SYSLOG)
  4450. addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified);
  4451. #if ELPP_ASYNC_LOGGING
  4452. installLogDispatchCallback<base::AsyncLogDispatchCallback>(std::string("AsyncLogDispatchCallback"));
  4453. #else
  4454. installLogDispatchCallback<base::DefaultLogDispatchCallback>(std::string("DefaultLogDispatchCallback"));
  4455. #endif // ELPP_ASYNC_LOGGING
  4456. installPerformanceTrackingCallback<base::DefaultPerformanceTrackingCallback>(std::string("DefaultPerformanceTrackingCallback"));
  4457. ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized");
  4458. #if ELPP_ASYNC_LOGGING
  4459. m_asyncDispatchWorker->start();
  4460. #endif // ELPP_ASYNC_LOGGING
  4461. }
  4462. virtual ~Storage(void)
  4463. {
  4464. ELPP_INTERNAL_INFO(4, "Destroying storage");
  4465. #if ELPP_ASYNC_LOGGING
  4466. ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous");
  4467. uninstallLogDispatchCallback<base::AsyncLogDispatchCallback>(std::string("AsyncLogDispatchCallback"));
  4468. installLogDispatchCallback<base::DefaultLogDispatchCallback>(std::string("DefaultLogDispatchCallback"));
  4469. ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker");
  4470. base::utils::safeDelete(m_asyncDispatchWorker);
  4471. ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue");
  4472. base::utils::safeDelete(m_asyncLogQueue);
  4473. #endif // ELPP_ASYNC_LOGGING
  4474. ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters");
  4475. base::utils::safeDelete(m_registeredHitCounters);
  4476. ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers");
  4477. base::utils::safeDelete(m_registeredLoggers);
  4478. ELPP_INTERNAL_INFO(5, "Destroying vRegistry");
  4479. base::utils::safeDelete(m_vRegistry);
  4480. }
  4481. inline bool validateEveryNCounter(const char* filename, unsigned long int lineNumber, std::size_t occasion)
  4482. {
  4483. return hitCounters()->validateEveryN(filename, lineNumber, occasion);
  4484. }
  4485. inline bool validateAfterNCounter(const char* filename, unsigned long int lineNumber, std::size_t n)
  4486. { // NOLINT
  4487. return hitCounters()->validateAfterN(filename, lineNumber, n);
  4488. }
  4489. inline bool validateNTimesCounter(const char* filename, unsigned long int lineNumber, std::size_t n)
  4490. { // NOLINT
  4491. return hitCounters()->validateNTimes(filename, lineNumber, n);
  4492. }
  4493. inline base::RegisteredHitCounters* hitCounters(void) const
  4494. {
  4495. return m_registeredHitCounters;
  4496. }
  4497. inline base::RegisteredLoggers* registeredLoggers(void) const
  4498. {
  4499. return m_registeredLoggers;
  4500. }
  4501. inline base::VRegistry* vRegistry(void) const
  4502. {
  4503. return m_vRegistry;
  4504. }
  4505. #if ELPP_ASYNC_LOGGING
  4506. inline base::AsyncLogQueue* asyncLogQueue(void) const
  4507. {
  4508. return m_asyncLogQueue;
  4509. }
  4510. #endif // ELPP_ASYNC_LOGGING
  4511. inline const base::utils::CommandLineArgs* commandLineArgs(void) const
  4512. {
  4513. return &m_commandLineArgs;
  4514. }
  4515. inline void addFlag(LoggingFlag flag)
  4516. {
  4517. base::utils::addFlag(flag, &m_flags);
  4518. }
  4519. inline void removeFlag(LoggingFlag flag)
  4520. {
  4521. base::utils::removeFlag(flag, &m_flags);
  4522. }
  4523. inline bool hasFlag(LoggingFlag flag) const
  4524. {
  4525. return base::utils::hasFlag(flag, m_flags);
  4526. }
  4527. inline base::type::EnumType flags(void) const
  4528. {
  4529. return m_flags;
  4530. }
  4531. inline void setFlags(base::type::EnumType flags)
  4532. {
  4533. m_flags = flags;
  4534. }
  4535. inline void setPreRollOutCallback(const PreRollOutCallback& callback)
  4536. {
  4537. m_preRollOutCallback = callback;
  4538. }
  4539. inline void unsetPreRollOutCallback(void)
  4540. {
  4541. m_preRollOutCallback = base::defaultPreRollOutCallback;
  4542. }
  4543. inline PreRollOutCallback& preRollOutCallback(void)
  4544. {
  4545. return m_preRollOutCallback;
  4546. }
  4547. inline bool hasCustomFormatSpecifier(const char* formatSpecifier)
  4548. {
  4549. base::threading::ScopedLock scopedLock(lock());
  4550. return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(),
  4551. formatSpecifier) != m_customFormatSpecifiers.end();
  4552. }
  4553. inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier)
  4554. {
  4555. if(hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier()))
  4556. {
  4557. return;
  4558. }
  4559. base::threading::ScopedLock scopedLock(lock());
  4560. m_customFormatSpecifiers.push_back(customFormatSpecifier);
  4561. }
  4562. inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier)
  4563. {
  4564. base::threading::ScopedLock scopedLock(lock());
  4565. std::vector<CustomFormatSpecifier>::iterator it = std::find(m_customFormatSpecifiers.begin(),
  4566. m_customFormatSpecifiers.end(), formatSpecifier);
  4567. if(it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0)
  4568. {
  4569. m_customFormatSpecifiers.erase(it);
  4570. return true;
  4571. }
  4572. return false;
  4573. }
  4574. const std::vector<CustomFormatSpecifier>* customFormatSpecifiers(void) const
  4575. {
  4576. return &m_customFormatSpecifiers;
  4577. }
  4578. inline void setLoggingLevel(Level level)
  4579. {
  4580. m_loggingLevel = level;
  4581. }
  4582. template <typename T>
  4583. inline bool installLogDispatchCallback(const std::string& id)
  4584. {
  4585. return installCallback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks);
  4586. }
  4587. template <typename T>
  4588. inline void uninstallLogDispatchCallback(const std::string& id)
  4589. {
  4590. uninstallCallback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks);
  4591. }
  4592. template <typename T>
  4593. inline T* logDispatchCallback(const std::string& id)
  4594. {
  4595. return callback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks);
  4596. }
  4597. template <typename T>
  4598. inline bool installPerformanceTrackingCallback(const std::string& id)
  4599. {
  4600. return installCallback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks);
  4601. }
  4602. template <typename T>
  4603. inline void uninstallPerformanceTrackingCallback(const std::string& id)
  4604. {
  4605. uninstallCallback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks);
  4606. }
  4607. template <typename T>
  4608. inline T* performanceTrackingCallback(const std::string& id)
  4609. {
  4610. return callback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks);
  4611. }
  4612. private:
  4613. base::RegisteredHitCounters* m_registeredHitCounters;
  4614. base::RegisteredLoggers* m_registeredLoggers;
  4615. base::type::EnumType m_flags;
  4616. base::VRegistry* m_vRegistry;
  4617. #if ELPP_ASYNC_LOGGING
  4618. base::AsyncLogQueue* m_asyncLogQueue;
  4619. base::IWorker* m_asyncDispatchWorker;
  4620. #endif // ELPP_ASYNC_LOGGING
  4621. base::utils::CommandLineArgs m_commandLineArgs;
  4622. PreRollOutCallback m_preRollOutCallback;
  4623. std::map<std::string, base::type::LogDispatchCallbackPtr> m_logDispatchCallbacks;
  4624. std::map<std::string, base::type::PerformanceTrackingCallbackPtr> m_performanceTrackingCallbacks;
  4625. std::vector<CustomFormatSpecifier> m_customFormatSpecifiers;
  4626. Level m_loggingLevel;
  4627. friend class el::Helpers;
  4628. friend class el::base::DefaultLogDispatchCallback;
  4629. friend class el::LogBuilder;
  4630. friend class el::base::MessageBuilder;
  4631. friend class el::base::Writer;
  4632. friend class el::base::PerformanceTracker;
  4633. friend class el::base::LogDispatcher;
  4634. void setApplicationArguments(int argc, char** argv)
  4635. {
  4636. m_commandLineArgs.setArgs(argc, argv);
  4637. m_vRegistry->setFromArgs(commandLineArgs());
  4638. // default log file
  4639. #if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
  4640. if(m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam))
  4641. {
  4642. Configurations c;
  4643. c.setGlobally(ConfigurationType::Filename, std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam)));
  4644. registeredLoggers()->setDefaultConfigurations(c);
  4645. for(base::RegisteredLoggers::iterator it = registeredLoggers()->begin();
  4646. it != registeredLoggers()->end(); ++it)
  4647. {
  4648. it->second->configure(c);
  4649. }
  4650. }
  4651. #endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG)
  4652. #if defined(ELPP_LOGGING_FLAGS_FROM_ARG)
  4653. if(m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam))
  4654. {
  4655. m_flags = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam));
  4656. }
  4657. #endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG)
  4658. }
  4659. inline void setApplicationArguments(int argc, const char** argv)
  4660. {
  4661. setApplicationArguments(argc, const_cast<char**>(argv));
  4662. }
  4663. template <typename T, typename TPtr>
  4664. inline bool installCallback(const std::string& id, std::map<std::string, TPtr>* mapT)
  4665. {
  4666. if(mapT->find(id) == mapT->end())
  4667. {
  4668. mapT->insert(std::make_pair(id, TPtr(new T())));
  4669. return true;
  4670. }
  4671. return false;
  4672. }
  4673. template <typename T, typename TPtr>
  4674. inline void uninstallCallback(const std::string& id, std::map<std::string, TPtr>* mapT)
  4675. {
  4676. if(mapT->find(id) != mapT->end())
  4677. {
  4678. mapT->erase(id);
  4679. }
  4680. }
  4681. template <typename T, typename TPtr>
  4682. inline T* callback(const std::string& id, std::map<std::string, TPtr>* mapT)
  4683. {
  4684. typename std::map<std::string, TPtr>::iterator iter = mapT->find(id);
  4685. if(iter != mapT->end())
  4686. {
  4687. return static_cast<T*>(iter->second.get());
  4688. }
  4689. return nullptr;
  4690. }
  4691. };
  4692. extern ELPP_EXPORT base::type::StoragePointer elStorage;
  4693. #define ELPP el::base::elStorage
  4694. class DefaultLogDispatchCallback : public LogDispatchCallback
  4695. {
  4696. protected:
  4697. void handle(const LogDispatchData* data)
  4698. {
  4699. m_data = data;
  4700. dispatch(std::move(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(),
  4701. m_data->dispatchAction() == base::DispatchAction::NormalLog)));
  4702. }
  4703. private:
  4704. const LogDispatchData* m_data;
  4705. void dispatch(base::type::string_t&& logLine)
  4706. {
  4707. if(m_data->dispatchAction() == base::DispatchAction::NormalLog)
  4708. {
  4709. if(m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level()))
  4710. {
  4711. base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream(m_data->logMessage()->level());
  4712. if(fs != nullptr)
  4713. {
  4714. fs->write(logLine.c_str(), logLine.size());
  4715. if(fs->fail())
  4716. {
  4717. ELPP_INTERNAL_ERROR("Unable to write log to file ["
  4718. << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n"
  4719. << "Few possible reasons (could be something else):\n" << " * Permission denied\n"
  4720. << " * Disk full\n" << " * Disk is not writable", true);
  4721. }
  4722. else
  4723. {
  4724. if(ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level())))
  4725. {
  4726. m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs);
  4727. }
  4728. }
  4729. }
  4730. else
  4731. {
  4732. ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] "
  4733. << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: "
  4734. << m_data->logMessage()->logger()->id() << "]", false);
  4735. }
  4736. }
  4737. if(m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level()))
  4738. {
  4739. if(ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
  4740. m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level());
  4741. ELPP_COUT << ELPP_COUT_LINE(logLine);
  4742. }
  4743. }
  4744. #if defined(ELPP_SYSLOG)
  4745. else if(m_data->dispatchAction() == base::DispatchAction::SysLog)
  4746. {
  4747. // Determine syslog priority
  4748. int sysLogPriority = 0;
  4749. if(m_data->logMessage()->level() == Level::Fatal)
  4750. sysLogPriority = LOG_EMERG;
  4751. else if(m_data->logMessage()->level() == Level::Error)
  4752. sysLogPriority = LOG_ERR;
  4753. else if(m_data->logMessage()->level() == Level::Warning)
  4754. sysLogPriority = LOG_WARNING;
  4755. else if(m_data->logMessage()->level() == Level::Info)
  4756. sysLogPriority = LOG_INFO;
  4757. else if(m_data->logMessage()->level() == Level::Debug)
  4758. sysLogPriority = LOG_DEBUG;
  4759. else
  4760. sysLogPriority = LOG_NOTICE;
  4761. # if defined(ELPP_UNICODE)
  4762. char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str());
  4763. syslog(sysLogPriority, "%s", line);
  4764. free(line);
  4765. # else
  4766. syslog(sysLogPriority, "%s", logLine.c_str());
  4767. # endif
  4768. }
  4769. #endif // defined(ELPP_SYSLOG)
  4770. }
  4771. };
  4772. #if ELPP_ASYNC_LOGGING
  4773. class AsyncLogDispatchCallback : public LogDispatchCallback
  4774. {
  4775. protected:
  4776. void handle(const LogDispatchData* data)
  4777. {
  4778. base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), data->dispatchAction() == base::DispatchAction::NormalLog);
  4779. if(data->dispatchAction() == base::DispatchAction::NormalLog && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level()))
  4780. {
  4781. if(ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
  4782. data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level());
  4783. ELPP_COUT << ELPP_COUT_LINE(logLine);
  4784. }
  4785. // Save resources and only queue if we want to write to file otherwise just ignore handler
  4786. if(data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level()))
  4787. {
  4788. ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine));
  4789. }
  4790. }
  4791. };
  4792. class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe
  4793. {
  4794. public:
  4795. AsyncDispatchWorker()
  4796. {
  4797. setContinueRunning(false);
  4798. }
  4799. virtual ~AsyncDispatchWorker()
  4800. {
  4801. setContinueRunning(false);
  4802. ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue");
  4803. clean();
  4804. ELPP_INTERNAL_INFO(6, "Log queue cleaned");
  4805. }
  4806. inline bool clean()
  4807. {
  4808. std::mutex m;
  4809. std::unique_lock<std::mutex> lk(m);
  4810. cv.wait(lk, []
  4811. {
  4812. return !ELPP->asyncLogQueue()->empty();
  4813. });
  4814. emptyQueue();
  4815. lk.unlock();
  4816. cv.notify_one();
  4817. return ELPP->asyncLogQueue()->empty();
  4818. }
  4819. inline void emptyQueue()
  4820. {
  4821. while(!ELPP->asyncLogQueue()->empty())
  4822. {
  4823. AsyncLogItem data = ELPP->asyncLogQueue()->next();
  4824. handle(&data);
  4825. base::threading::msleep(100);
  4826. }
  4827. }
  4828. virtual inline void start()
  4829. {
  4830. base::threading::msleep(5000); // Wait extra few seconds
  4831. setContinueRunning(true);
  4832. std::thread t1(&AsyncDispatchWorker::runner, this);
  4833. t1.join();
  4834. }
  4835. void handle(AsyncLogItem* logItem)
  4836. {
  4837. LogDispatchData* data = logItem->data();
  4838. LogMessage* logMessage = logItem->logMessage();
  4839. Logger* logger = logMessage->logger();
  4840. base::TypedConfigurations* conf = logger->typedConfigurations();
  4841. base::type::string_t logLine = logItem->logLine();
  4842. if(data->dispatchAction() == base::DispatchAction::NormalLog)
  4843. {
  4844. if(conf->toFile(logMessage->level()))
  4845. {
  4846. base::type::fstream_t* fs = conf->fileStream(logMessage->level());
  4847. if(fs != nullptr)
  4848. {
  4849. fs->write(logLine.c_str(), logLine.size());
  4850. if(fs->fail())
  4851. {
  4852. ELPP_INTERNAL_ERROR("Unable to write log to file ["
  4853. << conf->filename(logMessage->level()) << "].\n"
  4854. << "Few possible reasons (could be something else):\n" << " * Permission denied\n"
  4855. << " * Disk full\n" << " * Disk is not writable", true);
  4856. }
  4857. else
  4858. {
  4859. if(ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level())))
  4860. {
  4861. logger->flush(logMessage->level(), fs);
  4862. }
  4863. }
  4864. }
  4865. else
  4866. {
  4867. ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] "
  4868. << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", false);
  4869. }
  4870. }
  4871. }
  4872. # if defined(ELPP_SYSLOG)
  4873. else if(data->dispatchAction() == base::DispatchAction::SysLog)
  4874. {
  4875. // Determine syslog priority
  4876. int sysLogPriority = 0;
  4877. if(logMessage->level() == Level::Fatal)
  4878. sysLogPriority = LOG_EMERG;
  4879. else if(logMessage->level() == Level::Error)
  4880. sysLogPriority = LOG_ERR;
  4881. else if(logMessage->level() == Level::Warning)
  4882. sysLogPriority = LOG_WARNING;
  4883. else if(logMessage->level() == Level::Info)
  4884. sysLogPriority = LOG_INFO;
  4885. else if(logMessage->level() == Level::Debug)
  4886. sysLogPriority = LOG_DEBUG;
  4887. else
  4888. sysLogPriority = LOG_NOTICE;
  4889. # if defined(ELPP_UNICODE)
  4890. char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str());
  4891. syslog(sysLogPriority, "%s", line);
  4892. free(line);
  4893. # else
  4894. syslog(sysLogPriority, "%s", logLine.c_str());
  4895. # endif
  4896. }
  4897. # endif // defined(ELPP_SYSLOG)
  4898. }
  4899. void run()
  4900. {
  4901. while(continueRunning())
  4902. {
  4903. emptyQueue();
  4904. base::threading::msleep(10); // 10ms
  4905. }
  4906. }
  4907. static void* runner(void* context)
  4908. {
  4909. static_cast<AsyncDispatchWorker*>(context)->run();
  4910. return NULL;
  4911. }
  4912. void setContinueRunning(bool value)
  4913. {
  4914. base::threading::ScopedLock scopedLock(m_continueRunningMutex);
  4915. m_continueRunning = value;
  4916. }
  4917. bool continueRunning(void)
  4918. {
  4919. return m_continueRunning;
  4920. }
  4921. private:
  4922. std::condition_variable cv;
  4923. bool m_continueRunning;
  4924. base::threading::Mutex m_continueRunningMutex;
  4925. };
  4926. #endif // ELPP_ASYNC_LOGGING
  4927. } // namespace base
  4928. namespace base {
  4929. class DefaultLogBuilder : public LogBuilder
  4930. {
  4931. public:
  4932. base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const
  4933. {
  4934. base::TypedConfigurations* tc = logMessage->logger()->typedConfigurations();
  4935. const base::LogFormat* logFormat = &tc->logFormat(logMessage->level());
  4936. base::type::string_t logLine = logFormat->format();
  4937. char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = "";
  4938. const char* bufLim = buff + sizeof(buff);
  4939. if(logFormat->hasFlag(base::FormatFlags::AppName))
  4940. {
  4941. // App name
  4942. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier,
  4943. logMessage->logger()->parentApplicationName());
  4944. }
  4945. if(logFormat->hasFlag(base::FormatFlags::ThreadId))
  4946. {
  4947. // Thread ID
  4948. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier,
  4949. base::threading::getCurrentThreadId());
  4950. }
  4951. if(logFormat->hasFlag(base::FormatFlags::DateTime))
  4952. {
  4953. // DateTime
  4954. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier,
  4955. base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(),
  4956. &tc->millisecondsWidth(logMessage->level())));
  4957. }
  4958. if(logFormat->hasFlag(base::FormatFlags::Function))
  4959. {
  4960. // Function
  4961. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func());
  4962. }
  4963. if(logFormat->hasFlag(base::FormatFlags::File))
  4964. {
  4965. // File
  4966. char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength);
  4967. base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff);
  4968. buf = base::utils::Str::addToBuff(buff, buf, bufLim);
  4969. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff));
  4970. }
  4971. if(logFormat->hasFlag(base::FormatFlags::FileBase))
  4972. {
  4973. // FileBase
  4974. char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength);
  4975. base::utils::File::buildBaseFilename(logMessage->file(), buff);
  4976. buf = base::utils::Str::addToBuff(buff, buf, bufLim);
  4977. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff));
  4978. }
  4979. if(logFormat->hasFlag(base::FormatFlags::Line))
  4980. {
  4981. // Line
  4982. char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength);
  4983. buf = base::utils::Str::convertAndAddToBuff(logMessage->line(),
  4984. base::consts::kSourceLineMaxLength, buf, bufLim, false);
  4985. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff));
  4986. }
  4987. if(logFormat->hasFlag(base::FormatFlags::Location))
  4988. {
  4989. // Location
  4990. char* buf = base::utils::Str::clearBuff(buff,
  4991. base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength);
  4992. base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff);
  4993. buf = base::utils::Str::addToBuff(buff, buf, bufLim);
  4994. buf = base::utils::Str::addToBuff(":", buf, bufLim);
  4995. buf = base::utils::Str::convertAndAddToBuff(logMessage->line(),
  4996. base::consts::kSourceLineMaxLength, buf, bufLim, false);
  4997. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff));
  4998. }
  4999. if(logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel))
  5000. {
  5001. // Verbose level
  5002. char* buf = base::utils::Str::clearBuff(buff, 1);
  5003. buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false);
  5004. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff));
  5005. }
  5006. if(logFormat->hasFlag(base::FormatFlags::LogMessage))
  5007. {
  5008. // Log message
  5009. base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message());
  5010. }
  5011. #if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS)
  5012. for(std::vector<CustomFormatSpecifier>::const_iterator it = ELPP->customFormatSpecifiers()->begin();
  5013. it != ELPP->customFormatSpecifiers()->end(); ++it)
  5014. {
  5015. std::string fs(it->formatSpecifier());
  5016. base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end());
  5017. base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, std::string(it->resolver()()));
  5018. }
  5019. #endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS)
  5020. if(appendNewLine) logLine += ELPP_LITERAL("\n");
  5021. return logLine;
  5022. }
  5023. };
  5024. /// @brief Dispatches log messages
  5025. class LogDispatcher : base::NoCopy
  5026. {
  5027. public:
  5028. LogDispatcher(bool proceed, LogMessage&& logMessage, base::DispatchAction dispatchAction) :
  5029. m_proceed(proceed),
  5030. m_logMessage(std::move(logMessage)),
  5031. m_dispatchAction(std::move(dispatchAction))
  5032. {
  5033. }
  5034. void dispatch(void)
  5035. {
  5036. if(m_proceed && m_dispatchAction == base::DispatchAction::None)
  5037. {
  5038. m_proceed = false;
  5039. }
  5040. if(!m_proceed)
  5041. {
  5042. return;
  5043. }
  5044. // We minimize the time of ELPP's lock - this lock is released after log is written
  5045. base::threading::ScopedLock scopedLock(ELPP->lock());
  5046. base::TypedConfigurations* tc = m_logMessage.logger()->m_typedConfigurations;
  5047. if(ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck))
  5048. {
  5049. tc->validateFileRolling(m_logMessage.level(), ELPP->preRollOutCallback());
  5050. }
  5051. LogDispatchCallback* callback = nullptr;
  5052. LogDispatchData data;
  5053. for(const std::pair<std::string, base::type::LogDispatchCallbackPtr>& h
  5054. : ELPP->m_logDispatchCallbacks)
  5055. {
  5056. callback = h.second.get();
  5057. if(callback != nullptr && callback->enabled())
  5058. {
  5059. data.setLogMessage(&m_logMessage);
  5060. data.setDispatchAction(m_dispatchAction);
  5061. callback->acquireLock();
  5062. callback->handle(&data);
  5063. callback->releaseLock();
  5064. }
  5065. }
  5066. }
  5067. private:
  5068. bool m_proceed;
  5069. LogMessage m_logMessage;
  5070. base::DispatchAction m_dispatchAction;
  5071. };
  5072. #if defined(ELPP_STL_LOGGING)
  5073. /// @brief Workarounds to write some STL logs
  5074. ///
  5075. /// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers
  5076. /// of same type and provide iterator interface and pass it on to writeIterator().
  5077. /// Remember, this is passed by value in constructor so that we dont change original containers.
  5078. /// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer))
  5079. namespace workarounds {
  5080. /// @brief Abstract IterableContainer template that provides interface for iterable classes of type T
  5081. template <typename T, typename Container>
  5082. class IterableContainer
  5083. {
  5084. public:
  5085. typedef typename Container::iterator iterator;
  5086. typedef typename Container::const_iterator const_iterator;
  5087. IterableContainer(void)
  5088. {
  5089. }
  5090. virtual ~IterableContainer(void)
  5091. {
  5092. }
  5093. iterator begin(void)
  5094. {
  5095. return getContainer().begin();
  5096. }
  5097. iterator end(void)
  5098. {
  5099. return getContainer().end();
  5100. }
  5101. private:
  5102. virtual Container& getContainer(void) = 0;
  5103. };
  5104. /// @brief Implements IterableContainer and provides iterable std::priority_queue class
  5105. template<typename T, typename Container = std::vector<T>, typename Comparator = std::less<typename Container::value_type>>
  5106. class IterablePriorityQueue : public IterableContainer<T, Container>, public std::priority_queue<T, Container, Comparator>
  5107. {
  5108. public:
  5109. IterablePriorityQueue(std::priority_queue<T, Container, Comparator> queue_)
  5110. {
  5111. std::size_t count_ = 0;
  5112. while(++count_ < base::consts::kMaxLogPerContainer && !queue_.empty())
  5113. {
  5114. this->push(queue_.top());
  5115. queue_.pop();
  5116. }
  5117. }
  5118. private:
  5119. inline Container& getContainer(void)
  5120. {
  5121. return this->c;
  5122. }
  5123. };
  5124. /// @brief Implements IterableContainer and provides iterable std::queue class
  5125. template<typename T, typename Container = std::deque<T>>
  5126. class IterableQueue : public IterableContainer<T, Container>, public std::queue<T, Container>
  5127. {
  5128. public:
  5129. IterableQueue(std::queue<T, Container> queue_)
  5130. {
  5131. std::size_t count_ = 0;
  5132. while(++count_ < base::consts::kMaxLogPerContainer && !queue_.empty())
  5133. {
  5134. this->push(queue_.front());
  5135. queue_.pop();
  5136. }
  5137. }
  5138. private:
  5139. inline Container& getContainer(void)
  5140. {
  5141. return this->c;
  5142. }
  5143. };
  5144. /// @brief Implements IterableContainer and provides iterable std::stack class
  5145. template<typename T, typename Container = std::deque<T>>
  5146. class IterableStack : public IterableContainer<T, Container>, public std::stack<T, Container>
  5147. {
  5148. public:
  5149. IterableStack(std::stack<T, Container> stack_)
  5150. {
  5151. std::size_t count_ = 0;
  5152. while(++count_ < base::consts::kMaxLogPerContainer && !stack_.empty())
  5153. {
  5154. this->push(stack_.top());
  5155. stack_.pop();
  5156. }
  5157. }
  5158. private:
  5159. inline Container& getContainer(void)
  5160. {
  5161. return this->c;
  5162. }
  5163. };
  5164. } // namespace workarounds
  5165. #endif // defined(ELPP_STL_LOGGING)
  5166. // Log message builder
  5167. class MessageBuilder
  5168. {
  5169. public:
  5170. MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL(""))
  5171. {
  5172. }
  5173. void initialize(Logger* logger)
  5174. {
  5175. m_logger = logger;
  5176. m_containerLogSeperator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ?
  5177. ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");
  5178. }
  5179. # define ELPP_SIMPLE_LOG(LOG_TYPE)\
  5180. inline MessageBuilder& operator<<(LOG_TYPE msg) {\
  5181. m_logger->stream() << msg;\
  5182. if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\
  5183. m_logger->stream() << " ";\
  5184. }\
  5185. return *this;\
  5186. }
  5187. inline MessageBuilder& operator<<(const std::string& msg)
  5188. {
  5189. return operator<<(msg.c_str());
  5190. }
  5191. ELPP_SIMPLE_LOG(char)
  5192. ELPP_SIMPLE_LOG(bool)
  5193. ELPP_SIMPLE_LOG(signed short)
  5194. ELPP_SIMPLE_LOG(unsigned short)
  5195. ELPP_SIMPLE_LOG(signed int)
  5196. ELPP_SIMPLE_LOG(unsigned int)
  5197. ELPP_SIMPLE_LOG(signed long)
  5198. ELPP_SIMPLE_LOG(unsigned long)
  5199. ELPP_SIMPLE_LOG(float)
  5200. ELPP_SIMPLE_LOG(double)
  5201. ELPP_SIMPLE_LOG(char*)
  5202. ELPP_SIMPLE_LOG(const char*)
  5203. ELPP_SIMPLE_LOG(const void*)
  5204. ELPP_SIMPLE_LOG(long double)
  5205. inline MessageBuilder& operator<<(const std::wstring& msg)
  5206. {
  5207. return operator<<(msg.c_str());
  5208. }
  5209. inline MessageBuilder& operator<<(const wchar_t* msg)
  5210. {
  5211. if(msg == nullptr)
  5212. {
  5213. m_logger->stream() << base::consts::kNullPointer;
  5214. return *this;
  5215. }
  5216. # if defined(ELPP_UNICODE)
  5217. m_logger->stream() << msg;
  5218. # else
  5219. char* buff_ = base::utils::Str::wcharPtrToCharPtr(msg);
  5220. m_logger->stream() << buff_;
  5221. free(buff_);
  5222. # endif
  5223. if(ELPP->hasFlag(LoggingFlag::AutoSpacing))
  5224. {
  5225. m_logger->stream() << " ";
  5226. }
  5227. return *this;
  5228. }
  5229. // ostream manipulators
  5230. inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&))
  5231. {
  5232. m_logger->stream() << OStreamMani;
  5233. return *this;
  5234. }
  5235. #define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \
  5236. template <typename T> \
  5237. inline MessageBuilder& operator<<(const temp<T>& template_inst) { \
  5238. return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \
  5239. }
  5240. #define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \
  5241. template <typename T1, typename T2> \
  5242. inline MessageBuilder& operator<<(const temp<T1, T2>& template_inst) { \
  5243. return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \
  5244. }
  5245. #define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \
  5246. template <typename T1, typename T2, typename T3> \
  5247. inline MessageBuilder& operator<<(const temp<T1, T2, T3>& template_inst) { \
  5248. return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \
  5249. }
  5250. #define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \
  5251. template <typename T1, typename T2, typename T3, typename T4> \
  5252. inline MessageBuilder& operator<<(const temp<T1, T2, T3, T4>& template_inst) { \
  5253. return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \
  5254. }
  5255. #define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \
  5256. template <typename T1, typename T2, typename T3, typename T4, typename T5> \
  5257. inline MessageBuilder& operator<<(const temp<T1, T2, T3, T4, T5>& template_inst) { \
  5258. return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \
  5259. }
  5260. #if defined(ELPP_STL_LOGGING)
  5261. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector)
  5262. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list)
  5263. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque)
  5264. ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set)
  5265. ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset)
  5266. ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map)
  5267. ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap)
  5268. template <class T, class Container>
  5269. inline MessageBuilder& operator<<(const std::queue<T, Container>& queue_)
  5270. {
  5271. base::workarounds::IterableQueue<T, Container> iterableQueue_ =
  5272. static_cast<base::workarounds::IterableQueue<T, Container>>(queue_);
  5273. return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size());
  5274. }
  5275. template <class T, class Container>
  5276. inline MessageBuilder& operator<<(const std::stack<T, Container>& stack_)
  5277. {
  5278. base::workarounds::IterableStack<T, Container> iterableStack_ =
  5279. static_cast<base::workarounds::IterableStack<T, Container>>(stack_);
  5280. return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size());
  5281. }
  5282. template <class T, class Container, class Comparator>
  5283. inline MessageBuilder& operator<<(const std::priority_queue<T, Container, Comparator>& priorityQueue_)
  5284. {
  5285. base::workarounds::IterablePriorityQueue<T, Container, Comparator> iterablePriorityQueue_ =
  5286. static_cast<base::workarounds::IterablePriorityQueue<T, Container, Comparator>>(priorityQueue_);
  5287. return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size());
  5288. }
  5289. template <class First, class Second>
  5290. inline MessageBuilder& operator<<(const std::pair<First, Second>& pair_)
  5291. {
  5292. m_logger->stream() << ELPP_LITERAL("(");
  5293. operator << (static_cast<First>(pair_.first));
  5294. m_logger->stream() << ELPP_LITERAL(", ");
  5295. operator << (static_cast<Second>(pair_.second));
  5296. m_logger->stream() << ELPP_LITERAL(")");
  5297. return *this;
  5298. }
  5299. template <std::size_t Size>
  5300. inline MessageBuilder& operator<<(const std::bitset<Size>& bitset_)
  5301. {
  5302. m_logger->stream() << ELPP_LITERAL("[");
  5303. operator << (bitset_.to_string());
  5304. m_logger->stream() << ELPP_LITERAL("]");
  5305. return *this;
  5306. }
  5307. # if defined(ELPP_LOG_STD_ARRAY)
  5308. template <class T, std::size_t Size>
  5309. inline MessageBuilder& operator<<(const std::array<T, Size>& array)
  5310. {
  5311. return writeIterator(array.begin(), array.end(), array.size());
  5312. }
  5313. # endif // defined(ELPP_LOG_STD_ARRAY)
  5314. # if defined(ELPP_LOG_UNORDERED_MAP)
  5315. ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map)
  5316. ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap)
  5317. # endif // defined(ELPP_LOG_UNORDERED_MAP)
  5318. # if defined(ELPP_LOG_UNORDERED_SET)
  5319. ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set)
  5320. ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset)
  5321. # endif // defined(ELPP_LOG_UNORDERED_SET)
  5322. #endif // defined(ELPP_STL_LOGGING)
  5323. #if defined(ELPP_QT_LOGGING)
  5324. inline MessageBuilder& operator<<(const QString& msg)
  5325. {
  5326. # if defined(ELPP_UNICODE)
  5327. m_logger->stream() << msg.toStdWString();
  5328. # else
  5329. m_logger->stream() << msg.toStdString();
  5330. # endif // defined(ELPP_UNICODE)
  5331. return *this;
  5332. }
  5333. inline MessageBuilder& operator<<(const QByteArray& msg)
  5334. {
  5335. return operator << (QString(msg));
  5336. }
  5337. inline MessageBuilder& operator<<(const QStringRef& msg)
  5338. {
  5339. return operator<<(msg.toString());
  5340. }
  5341. inline MessageBuilder& operator<<(qint64 msg)
  5342. {
  5343. # if defined(ELPP_UNICODE)
  5344. m_logger->stream() << QString::number(msg).toStdWString();
  5345. # else
  5346. m_logger->stream() << QString::number(msg).toStdString();
  5347. # endif // defined(ELPP_UNICODE)
  5348. return *this;
  5349. }
  5350. inline MessageBuilder& operator<<(quint64 msg)
  5351. {
  5352. # if defined(ELPP_UNICODE)
  5353. m_logger->stream() << QString::number(msg).toStdWString();
  5354. # else
  5355. m_logger->stream() << QString::number(msg).toStdString();
  5356. # endif // defined(ELPP_UNICODE)
  5357. return *this;
  5358. }
  5359. inline MessageBuilder& operator<<(QChar msg)
  5360. {
  5361. m_logger->stream() << msg.toLatin1();
  5362. return *this;
  5363. }
  5364. inline MessageBuilder& operator<<(const QLatin1String& msg)
  5365. {
  5366. m_logger->stream() << msg.latin1();
  5367. return *this;
  5368. }
  5369. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList)
  5370. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector)
  5371. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue)
  5372. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet)
  5373. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList)
  5374. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack)
  5375. template <typename First, typename Second>
  5376. inline MessageBuilder& operator<<(const QPair<First, Second>& pair_)
  5377. {
  5378. m_logger->stream() << ELPP_LITERAL("(");
  5379. operator << (static_cast<First>(pair_.first));
  5380. m_logger->stream() << ELPP_LITERAL(", ");
  5381. operator << (static_cast<Second>(pair_.second));
  5382. m_logger->stream() << ELPP_LITERAL(")");
  5383. return *this;
  5384. }
  5385. template <typename K, typename V>
  5386. inline MessageBuilder& operator<<(const QMap<K, V>& map_)
  5387. {
  5388. m_logger->stream() << ELPP_LITERAL("[");
  5389. QList<K> keys = map_.keys();
  5390. typename QList<K>::const_iterator begin = keys.begin();
  5391. typename QList<K>::const_iterator end = keys.end();
  5392. int max_ = static_cast<int>(base::consts::kMaxLogPerContainer); // to prevent warning
  5393. for(int index_ = 0; begin != end && index_ < max_; ++index_, ++begin)
  5394. {
  5395. m_logger->stream() << ELPP_LITERAL("(");
  5396. operator << (static_cast<K>(*begin));
  5397. m_logger->stream() << ELPP_LITERAL(", ");
  5398. operator << (static_cast<V>(map_.value(*begin)));
  5399. m_logger->stream() << ELPP_LITERAL(")");
  5400. m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL(""));
  5401. }
  5402. if(begin != end)
  5403. {
  5404. m_logger->stream() << ELPP_LITERAL("...");
  5405. }
  5406. m_logger->stream() << ELPP_LITERAL("]");
  5407. return *this;
  5408. }
  5409. template <typename K, typename V>
  5410. inline MessageBuilder& operator<<(const QMultiMap<K, V>& map_)
  5411. {
  5412. operator << (static_cast<QMap<K, V>>(map_));
  5413. return *this;
  5414. }
  5415. template <typename K, typename V>
  5416. inline MessageBuilder& operator<<(const QHash<K, V>& hash_)
  5417. {
  5418. m_logger->stream() << ELPP_LITERAL("[");
  5419. QList<K> keys = hash_.keys();
  5420. typename QList<K>::const_iterator begin = keys.begin();
  5421. typename QList<K>::const_iterator end = keys.end();
  5422. int max_ = static_cast<int>(base::consts::kMaxLogPerContainer); // prevent type warning
  5423. for(int index_ = 0; begin != end && index_ < max_; ++index_, ++begin)
  5424. {
  5425. m_logger->stream() << ELPP_LITERAL("(");
  5426. operator << (static_cast<K>(*begin));
  5427. m_logger->stream() << ELPP_LITERAL(", ");
  5428. operator << (static_cast<V>(hash_.value(*begin)));
  5429. m_logger->stream() << ELPP_LITERAL(")");
  5430. m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL(""));
  5431. }
  5432. if(begin != end)
  5433. {
  5434. m_logger->stream() << ELPP_LITERAL("...");
  5435. }
  5436. m_logger->stream() << ELPP_LITERAL("]");
  5437. return *this;
  5438. }
  5439. template <typename K, typename V>
  5440. inline MessageBuilder& operator<<(const QMultiHash<K, V>& multiHash_)
  5441. {
  5442. operator << (static_cast<QHash<K, V>>(multiHash_));
  5443. return *this;
  5444. }
  5445. #endif // defined(ELPP_QT_LOGGING)
  5446. #if defined(ELPP_BOOST_LOGGING)
  5447. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector)
  5448. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector)
  5449. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list)
  5450. ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque)
  5451. ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map)
  5452. ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map)
  5453. ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set)
  5454. ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set)
  5455. #endif // defined(ELPP_BOOST_LOGGING)
  5456. /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly
  5457. ///
  5458. /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to
  5459. /// have begin() and end() methods that return respective iterators
  5460. /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets
  5461. /// @param SizeMethod Method used to get size of container.
  5462. /// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro
  5463. /// for an example usage
  5464. #define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \
  5465. el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\
  5466. const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \
  5467. ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\
  5468. ContainerType::const_iterator elem = container.begin();\
  5469. ContainerType::const_iterator endElem = container.end();\
  5470. std::size_t size_ = container.SizeMethod; \
  5471. ss << ELPP_LITERAL("[");\
  5472. for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \
  5473. ss << ElementInstance;\
  5474. ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\
  5475. }\
  5476. if (elem != endElem) {\
  5477. ss << ELPP_LITERAL("...");\
  5478. }\
  5479. ss << ELPP_LITERAL("]");\
  5480. return ss;\
  5481. }
  5482. #if defined(ELPP_WXWIDGETS_LOGGING)
  5483. ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector)
  5484. # define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem))
  5485. # define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem))
  5486. # define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \
  5487. ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")")
  5488. #else
  5489. # define ELPP_WX_PTR_ENABLED(ContainerType)
  5490. # define ELPP_WX_ENABLED(ContainerType)
  5491. # define ELPP_WX_HASH_MAP_ENABLED(ContainerType)
  5492. #endif // defined(ELPP_WXWIDGETS_LOGGING)
  5493. // Other classes
  5494. template <class Class>
  5495. ELPP_SIMPLE_LOG(const Class&)
  5496. #undef ELPP_SIMPLE_LOG
  5497. #undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG
  5498. #undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG
  5499. #undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG
  5500. #undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG
  5501. #undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG
  5502. private:
  5503. Logger* m_logger;
  5504. const base::type::char_t* m_containerLogSeperator;
  5505. template<class Iterator>
  5506. inline MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_)
  5507. {
  5508. m_logger->stream() << ELPP_LITERAL("[");
  5509. for(std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_)
  5510. {
  5511. operator << (*begin_);
  5512. m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL(""));
  5513. }
  5514. if(begin_ != end_)
  5515. {
  5516. m_logger->stream() << ELPP_LITERAL("...");
  5517. }
  5518. m_logger->stream() << ELPP_LITERAL("]");
  5519. if(ELPP->hasFlag(LoggingFlag::AutoSpacing))
  5520. {
  5521. m_logger->stream() << " ";
  5522. }
  5523. return *this;
  5524. }
  5525. };
  5526. /// @brief Writes nothing - Used when certain log is disabled
  5527. class NullWriter : base::NoCopy
  5528. {
  5529. public:
  5530. NullWriter(void)
  5531. {
  5532. }
  5533. // Null manipulator
  5534. inline NullWriter& operator<<(std::ostream& (*)(std::ostream&))
  5535. {
  5536. return *this;
  5537. }
  5538. template <typename T>
  5539. inline NullWriter& operator<<(const T&)
  5540. {
  5541. return *this;
  5542. }
  5543. };
  5544. /// @brief Main entry point of each logging
  5545. class Writer : base::NoCopy
  5546. {
  5547. public:
  5548. Writer(Level level, const char* file, unsigned long int line,
  5549. const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
  5550. base::type::VerboseLevel verboseLevel = 0) :
  5551. m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel),
  5552. m_proceed(false), m_dispatchAction(dispatchAction)
  5553. {
  5554. }
  5555. virtual ~Writer(void)
  5556. {
  5557. processDispatch();
  5558. }
  5559. template <typename T>
  5560. inline Writer& operator<<(const T& log)
  5561. {
  5562. #if ELPP_LOGGING_ENABLED
  5563. if(m_proceed)
  5564. {
  5565. m_messageBuilder << log;
  5566. }
  5567. #endif // ELPP_LOGGING_ENABLED
  5568. return *this;
  5569. }
  5570. inline Writer& operator<<(std::ostream& (*log)(std::ostream&))
  5571. {
  5572. #if ELPP_LOGGING_ENABLED
  5573. if(m_proceed)
  5574. {
  5575. m_messageBuilder << log;
  5576. }
  5577. #endif // ELPP_LOGGING_ENABLED
  5578. return *this;
  5579. }
  5580. Writer& construct(Logger* logger, bool needLock = true)
  5581. {
  5582. m_logger = logger;
  5583. initializeLogger(logger->id(), false, needLock);
  5584. m_messageBuilder.initialize(m_logger);
  5585. return *this;
  5586. }
  5587. Writer& construct(int count, const char* loggerIds, ...)
  5588. {
  5589. if(ELPP->hasFlag(LoggingFlag::MultiLoggerSupport))
  5590. {
  5591. va_list loggersList;
  5592. va_start(loggersList, loggerIds);
  5593. const char* id = loggerIds;
  5594. for(int i = 0; i < count; ++i)
  5595. {
  5596. m_loggerIds.push_back(std::string(id));
  5597. id = va_arg(loggersList, const char*);
  5598. }
  5599. va_end(loggersList);
  5600. initializeLogger(m_loggerIds.at(0));
  5601. }
  5602. else
  5603. {
  5604. initializeLogger(std::string(loggerIds));
  5605. }
  5606. m_messageBuilder.initialize(m_logger);
  5607. return *this;
  5608. }
  5609. protected:
  5610. Level m_level;
  5611. const char* m_file;
  5612. const unsigned long int m_line;
  5613. const char* m_func;
  5614. base::type::VerboseLevel m_verboseLevel;
  5615. Logger* m_logger;
  5616. bool m_proceed;
  5617. base::MessageBuilder m_messageBuilder;
  5618. base::DispatchAction m_dispatchAction;
  5619. std::vector<std::string> m_loggerIds;
  5620. friend class el::Helpers;
  5621. void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true)
  5622. {
  5623. if(lookup)
  5624. {
  5625. m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically));
  5626. }
  5627. if(m_logger == nullptr)
  5628. {
  5629. ELPP->acquireLock();
  5630. if(!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId)))
  5631. {
  5632. // Somehow default logger has been unregistered. Not good! Register again
  5633. ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId));
  5634. }
  5635. ELPP->releaseLock(); // Need to unlock it for next writer
  5636. Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
  5637. << "Logger [" << loggerId << "] is not registered yet!";
  5638. m_proceed = false;
  5639. }
  5640. else
  5641. {
  5642. if(needLock)
  5643. {
  5644. m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because
  5645. // m_proceed can be changed by lines below
  5646. }
  5647. if(ELPP->hasFlag(LoggingFlag::HierarchicalLogging))
  5648. {
  5649. m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) :
  5650. LevelHelper::castToInt(m_level) >= LevelHelper::castToInt(ELPP->m_loggingLevel);
  5651. }
  5652. else
  5653. {
  5654. m_proceed = m_logger->enabled(m_level);
  5655. }
  5656. }
  5657. }
  5658. void processDispatch()
  5659. {
  5660. #if ELPP_LOGGING_ENABLED
  5661. if(ELPP->hasFlag(LoggingFlag::MultiLoggerSupport))
  5662. {
  5663. bool firstDispatched = false;
  5664. base::type::string_t logMessage;
  5665. std::size_t i = 0;
  5666. do
  5667. {
  5668. if(m_proceed)
  5669. {
  5670. if(firstDispatched)
  5671. {
  5672. m_logger->stream() << logMessage;
  5673. }
  5674. else
  5675. {
  5676. firstDispatched = true;
  5677. if(m_loggerIds.size() > 1)
  5678. {
  5679. logMessage = m_logger->stream().str();
  5680. }
  5681. }
  5682. triggerDispatch();
  5683. }
  5684. else if(m_logger != nullptr)
  5685. {
  5686. m_logger->stream().str(ELPP_LITERAL(""));
  5687. m_logger->releaseLock();
  5688. }
  5689. if(i + 1 < m_loggerIds.size())
  5690. {
  5691. initializeLogger(m_loggerIds.at(i + 1));
  5692. }
  5693. } while(++i < m_loggerIds.size());
  5694. }
  5695. else
  5696. {
  5697. if(m_proceed)
  5698. {
  5699. triggerDispatch();
  5700. }
  5701. else if(m_logger != nullptr)
  5702. {
  5703. m_logger->stream().str(ELPP_LITERAL(""));
  5704. m_logger->releaseLock();
  5705. }
  5706. }
  5707. #else
  5708. if(m_logger != nullptr)
  5709. {
  5710. m_logger->stream().str(ELPP_LITERAL(""));
  5711. m_logger->releaseLock();
  5712. }
  5713. #endif // ELPP_LOGGING_ENABLED
  5714. }
  5715. void triggerDispatch(void)
  5716. {
  5717. if(m_proceed)
  5718. {
  5719. base::LogDispatcher(m_proceed, LogMessage(m_level, m_file, m_line, m_func, m_verboseLevel,
  5720. m_logger), m_dispatchAction).dispatch();
  5721. }
  5722. if(m_logger != nullptr)
  5723. {
  5724. m_logger->stream().str(ELPP_LITERAL(""));
  5725. m_logger->releaseLock();
  5726. }
  5727. if(m_proceed && m_level == Level::Fatal
  5728. && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog))
  5729. {
  5730. base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
  5731. << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]";
  5732. std::stringstream reasonStream;
  5733. reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]"
  5734. << " If you wish to disable 'abort on fatal log' please use "
  5735. << "el::Helpers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)";
  5736. base::utils::abort(1, reasonStream.str());
  5737. }
  5738. m_proceed = false;
  5739. }
  5740. };
  5741. class PErrorWriter : public base::Writer
  5742. {
  5743. public:
  5744. PErrorWriter(Level level, const char* file, unsigned long int line,
  5745. const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
  5746. base::type::VerboseLevel verboseLevel = 0) :
  5747. base::Writer(level, file, line, func, dispatchAction, verboseLevel)
  5748. {
  5749. }
  5750. virtual ~PErrorWriter(void)
  5751. {
  5752. if(m_proceed)
  5753. {
  5754. #if ELPP_COMPILER_MSVC
  5755. char buff[256];
  5756. strerror_s(buff, 256, errno);
  5757. m_logger->stream() << ": " << buff << " [" << errno << "]";
  5758. #else
  5759. m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]";
  5760. #endif
  5761. }
  5762. }
  5763. };
  5764. } // namespace base
  5765. // Logging from Logger class. Why this is here? Because we have Storage and Writer class available
  5766. #if ELPP_VARIADIC_TEMPLATES_SUPPORTED
  5767. template <typename T, typename... Args>
  5768. void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args)
  5769. {
  5770. base::MessageBuilder b;
  5771. b.initialize(this);
  5772. while(*s)
  5773. {
  5774. if(*s == base::consts::kFormatSpecifierChar)
  5775. {
  5776. if(*(s + 1) == base::consts::kFormatSpecifierChar)
  5777. {
  5778. ++s;
  5779. }
  5780. else
  5781. {
  5782. if(*(s + 1) == base::consts::kFormatSpecifierCharValue)
  5783. {
  5784. ++s;
  5785. b << value;
  5786. log_(level, vlevel, ++s, args...);
  5787. return;
  5788. }
  5789. }
  5790. }
  5791. b << *s++;
  5792. }
  5793. ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false);
  5794. }
  5795. template <typename T>
  5796. inline void Logger::log_(Level level, int vlevel, const T& log)
  5797. {
  5798. if(level == Level::Verbose)
  5799. {
  5800. if(ELPP->vRegistry()->allowed(vlevel, __FILE__))
  5801. {
  5802. base::Writer(Level::Verbose, "FILE", 0, "FUNCTION",
  5803. base::DispatchAction::NormalLog, vlevel).construct(this, false) << log;
  5804. }
  5805. else
  5806. {
  5807. stream().str(ELPP_LITERAL(""));
  5808. }
  5809. }
  5810. else
  5811. {
  5812. base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log;
  5813. }
  5814. }
  5815. template <typename T, typename... Args>
  5816. void Logger::log(Level level, const char* s, const T& value, const Args&... args)
  5817. {
  5818. base::threading::ScopedLock scopedLock(lock());
  5819. log_(level, 0, s, value, args...);
  5820. }
  5821. template <typename T>
  5822. inline void Logger::log(Level level, const T& log)
  5823. {
  5824. base::threading::ScopedLock scopedLock(lock());
  5825. log_(level, 0, log);
  5826. }
  5827. # if ELPP_VERBOSE_LOG
  5828. template <typename T, typename... Args>
  5829. inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args)
  5830. {
  5831. base::threading::ScopedLock scopedLock(lock());
  5832. log_(el::Level::Verbose, vlevel, s, value, args...);
  5833. }
  5834. template <typename T>
  5835. inline void Logger::verbose(int vlevel, const T& log)
  5836. {
  5837. base::threading::ScopedLock scopedLock(lock());
  5838. log_(el::Level::Verbose, vlevel, log);
  5839. }
  5840. # else
  5841. template <typename T, typename... Args>
  5842. inline void Logger::verbose(int, const char*, const T&, const Args&...)
  5843. {
  5844. return;
  5845. }
  5846. template <typename T>
  5847. inline void Logger::verbose(int, const T&)
  5848. {
  5849. return;
  5850. }
  5851. # endif // ELPP_VERBOSE_LOG
  5852. # define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\
  5853. template <typename T, typename... Args>\
  5854. inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\
  5855. log(LOG_LEVEL, s, value, args...);\
  5856. }\
  5857. template <typename T>\
  5858. inline void Logger::FUNCTION_NAME(const T& value) {\
  5859. log(LOG_LEVEL, value);\
  5860. }
  5861. # define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\
  5862. template <typename T, typename... Args>\
  5863. inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\
  5864. return;\
  5865. }\
  5866. template <typename T>\
  5867. inline void Logger::FUNCTION_NAME(const T&) {\
  5868. return;\
  5869. }
  5870. # if ELPP_INFO_LOG
  5871. LOGGER_LEVEL_WRITERS(info, Level::Info)
  5872. # else
  5873. LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info)
  5874. # endif // ELPP_INFO_LOG
  5875. # if ELPP_DEBUG_LOG
  5876. LOGGER_LEVEL_WRITERS(debug, Level::Debug)
  5877. # else
  5878. LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug)
  5879. # endif // ELPP_DEBUG_LOG
  5880. # if ELPP_WARNING_LOG
  5881. LOGGER_LEVEL_WRITERS(warn, Level::Warning)
  5882. # else
  5883. LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning)
  5884. # endif // ELPP_WARNING_LOG
  5885. # if ELPP_ERROR_LOG
  5886. LOGGER_LEVEL_WRITERS(error, Level::Error)
  5887. # else
  5888. LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error)
  5889. # endif // ELPP_ERROR_LOG
  5890. # if ELPP_FATAL_LOG
  5891. LOGGER_LEVEL_WRITERS(fatal, Level::Fatal)
  5892. # else
  5893. LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal)
  5894. # endif // ELPP_FATAL_LOG
  5895. # if ELPP_TRACE_LOG
  5896. LOGGER_LEVEL_WRITERS(trace, Level::Trace)
  5897. # else
  5898. LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace)
  5899. # endif // ELPP_TRACE_LOG
  5900. # undef LOGGER_LEVEL_WRITERS
  5901. # undef LOGGER_LEVEL_WRITERS_DISABLED
  5902. #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED
  5903. #if ELPP_COMPILER_MSVC
  5904. # define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs
  5905. # define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__))
  5906. # define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\
  5907. 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
  5908. #else
  5909. # if ELPP_COMPILER_CLANG
  5910. # define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
  5911. # else
  5912. # define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
  5913. # endif // ELPP_COMPILER_CLANG
  5914. #endif // ELPP_COMPILER_MSVC
  5915. #define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
  5916. #define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \
  5917. writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  5918. #define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \
  5919. writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  5920. #define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \
  5921. if (ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion)) \
  5922. writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  5923. #define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \
  5924. if (ELPP->validateAfterNCounter(__FILE__, __LINE__, n)) \
  5925. writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  5926. #define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \
  5927. if (ELPP->validateNTimesCounter(__FILE__, __LINE__, n)) \
  5928. writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  5929. #undef ELPP_CURR_FILE_PERFORMANCE_LOGGER
  5930. #if defined(ELPP_PERFORMANCE_LOGGER)
  5931. # define ELPP_CURR_FILE_PERFORMANCE_LOGGER ELPP_PERFORMANCE_LOGGER
  5932. #else
  5933. # define ELPP_CURR_FILE_PERFORMANCE_LOGGER el::base::consts::kPerformanceLoggerId
  5934. #endif
  5935. class PerformanceTrackingData
  5936. {
  5937. public:
  5938. enum class DataType : base::type::EnumType
  5939. {
  5940. Checkpoint = 1, Complete = 2
  5941. };
  5942. // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*)
  5943. explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr),
  5944. m_dataType(dataType), m_file(""), m_line(0), m_func("")
  5945. {
  5946. }
  5947. inline const std::string* blockName(void) const;
  5948. inline const struct timeval* startTime(void) const;
  5949. inline const struct timeval* endTime(void) const;
  5950. inline const struct timeval* lastCheckpointTime(void) const;
  5951. inline const base::PerformanceTracker* performanceTracker(void) const
  5952. {
  5953. return m_performanceTracker;
  5954. }
  5955. inline PerformanceTrackingData::DataType dataType(void) const
  5956. {
  5957. return m_dataType;
  5958. }
  5959. inline bool firstCheckpoint(void) const
  5960. {
  5961. return m_firstCheckpoint;
  5962. }
  5963. inline std::string checkpointId(void) const
  5964. {
  5965. return m_checkpointId;
  5966. }
  5967. inline const char* file(void) const
  5968. {
  5969. return m_file;
  5970. }
  5971. inline unsigned long int line(void) const
  5972. {
  5973. return m_line;
  5974. }
  5975. inline const char* func(void) const
  5976. {
  5977. return m_func;
  5978. }
  5979. inline const base::type::string_t* formattedTimeTaken() const
  5980. {
  5981. return &m_formattedTimeTaken;
  5982. }
  5983. inline const std::string& loggerId(void) const;
  5984. private:
  5985. base::PerformanceTracker* m_performanceTracker;
  5986. base::type::string_t m_formattedTimeTaken;
  5987. PerformanceTrackingData::DataType m_dataType;
  5988. bool m_firstCheckpoint;
  5989. std::string m_checkpointId;
  5990. const char* m_file;
  5991. unsigned long int m_line;
  5992. const char* m_func;
  5993. inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false)
  5994. {
  5995. m_performanceTracker = performanceTracker;
  5996. m_firstCheckpoint = firstCheckpoint;
  5997. }
  5998. friend class el::base::PerformanceTracker;
  5999. };
  6000. namespace base {
  6001. /// @brief Represents performanceTracker block of code that conditionally adds performance status to log
  6002. /// either when goes outside the scope of when checkpoint() is called
  6003. class PerformanceTracker : public base::threading::ThreadSafe, public Loggable
  6004. {
  6005. public:
  6006. PerformanceTracker(const std::string& blockName,
  6007. base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond,
  6008. const std::string& loggerId = std::string(ELPP_CURR_FILE_PERFORMANCE_LOGGER),
  6009. bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel) :
  6010. m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog),
  6011. m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false)
  6012. {
  6013. #if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
  6014. // We store it locally so that if user happen to change configuration by the end of scope
  6015. // or before calling checkpoint, we still depend on state of configuraton at time of construction
  6016. el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false);
  6017. m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level);
  6018. if(m_enabled)
  6019. {
  6020. base::utils::DateTime::gettimeofday(&m_startTime);
  6021. }
  6022. #endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
  6023. }
  6024. /// @brief Copy constructor
  6025. PerformanceTracker(const PerformanceTracker& t) :
  6026. m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog),
  6027. m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled),
  6028. m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime)
  6029. {
  6030. }
  6031. virtual ~PerformanceTracker(void)
  6032. {
  6033. #if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
  6034. if(m_enabled)
  6035. {
  6036. base::threading::ScopedLock scopedLock(lock());
  6037. if(m_scopedLog)
  6038. {
  6039. base::utils::DateTime::gettimeofday(&m_endTime);
  6040. base::type::string_t formattedTime = getFormattedTimeTaken();
  6041. PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete);
  6042. data.init(this);
  6043. data.m_formattedTimeTaken = formattedTime;
  6044. PerformanceTrackingCallback* callback = nullptr;
  6045. for(const std::pair<std::string, base::type::PerformanceTrackingCallbackPtr>& h
  6046. : ELPP->m_performanceTrackingCallbacks)
  6047. {
  6048. callback = h.second.get();
  6049. if(callback != nullptr && callback->enabled())
  6050. {
  6051. callback->acquireLock();
  6052. callback->handle(&data);
  6053. callback->releaseLock();
  6054. }
  6055. }
  6056. }
  6057. }
  6058. #endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING)
  6059. }
  6060. /// @brief A checkpoint for current performanceTracker block.
  6061. void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, unsigned long int line = __LINE__, const char* func = "")
  6062. {
  6063. #if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
  6064. if(m_enabled)
  6065. {
  6066. base::threading::ScopedLock scopedLock(lock());
  6067. base::utils::DateTime::gettimeofday(&m_endTime);
  6068. base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL("");
  6069. PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint);
  6070. data.init(this);
  6071. data.m_checkpointId = id;
  6072. data.m_file = file;
  6073. data.m_line = line;
  6074. data.m_func = func;
  6075. data.m_formattedTimeTaken = formattedTime;
  6076. PerformanceTrackingCallback* callback = nullptr;
  6077. for(const std::pair<std::string, base::type::PerformanceTrackingCallbackPtr>& h
  6078. : ELPP->m_performanceTrackingCallbacks)
  6079. {
  6080. callback = h.second.get();
  6081. if(callback != nullptr && callback->enabled())
  6082. {
  6083. callback->acquireLock();
  6084. callback->handle(&data);
  6085. callback->releaseLock();
  6086. }
  6087. }
  6088. base::utils::DateTime::gettimeofday(&m_lastCheckpointTime);
  6089. m_hasChecked = true;
  6090. m_lastCheckpointId = id;
  6091. }
  6092. #endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
  6093. ELPP_UNUSED(id);
  6094. ELPP_UNUSED(file);
  6095. ELPP_UNUSED(line);
  6096. ELPP_UNUSED(func);
  6097. }
  6098. inline Level level(void) const
  6099. {
  6100. return m_level;
  6101. }
  6102. private:
  6103. std::string m_blockName;
  6104. base::TimestampUnit m_timestampUnit;
  6105. std::string m_loggerId;
  6106. bool m_scopedLog;
  6107. Level m_level;
  6108. bool m_hasChecked;
  6109. std::string m_lastCheckpointId;
  6110. bool m_enabled;
  6111. struct timeval m_startTime, m_endTime, m_lastCheckpointTime;
  6112. PerformanceTracker(void);
  6113. friend class el::PerformanceTrackingData;
  6114. friend class base::DefaultPerformanceTrackingCallback;
  6115. const inline base::type::string_t getFormattedTimeTaken() const
  6116. {
  6117. return getFormattedTimeTaken(m_startTime);
  6118. }
  6119. const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const
  6120. {
  6121. if(ELPP->hasFlag(LoggingFlag::FixedTimeFormat))
  6122. {
  6123. base::type::stringstream_t ss;
  6124. ss << base::utils::DateTime::getTimeDifference(m_endTime,
  6125. startTime, m_timestampUnit) << " " << base::consts::kTimeFormats[static_cast<base::type::EnumType>(m_timestampUnit)].unit;
  6126. return ss.str();
  6127. }
  6128. return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime,
  6129. startTime, m_timestampUnit), m_timestampUnit);
  6130. }
  6131. virtual inline void log(el::base::type::ostream_t& os) const
  6132. {
  6133. os << getFormattedTimeTaken();
  6134. }
  6135. };
  6136. class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback
  6137. {
  6138. protected:
  6139. void handle(const PerformanceTrackingData* data)
  6140. {
  6141. m_data = data;
  6142. base::type::stringstream_t ss;
  6143. if(m_data->dataType() == PerformanceTrackingData::DataType::Complete)
  6144. {
  6145. ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << *m_data->formattedTimeTaken() << ELPP_LITERAL("]");
  6146. }
  6147. else
  6148. {
  6149. ss << ELPP_LITERAL("Performance checkpoint");
  6150. if(!m_data->checkpointId().empty())
  6151. {
  6152. ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]");
  6153. }
  6154. ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << *m_data->performanceTracker();
  6155. if(!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) && m_data->performanceTracker()->m_hasChecked)
  6156. {
  6157. ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from ");
  6158. if(m_data->performanceTracker()->m_lastCheckpointId.empty())
  6159. {
  6160. ss << ELPP_LITERAL("last checkpoint");
  6161. }
  6162. else
  6163. {
  6164. ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'");
  6165. }
  6166. ss << ELPP_LITERAL(")]");
  6167. }
  6168. else
  6169. {
  6170. ss << ELPP_LITERAL("]");
  6171. }
  6172. }
  6173. el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, m_data->loggerId().c_str()) << ss.str();
  6174. }
  6175. private:
  6176. const PerformanceTrackingData* m_data;
  6177. };
  6178. } // namespace base
  6179. inline const std::string* PerformanceTrackingData::blockName() const
  6180. {
  6181. return const_cast<const std::string*>(&m_performanceTracker->m_blockName);
  6182. }
  6183. inline const struct timeval* PerformanceTrackingData::startTime() const
  6184. {
  6185. return const_cast<const struct timeval*>(&m_performanceTracker->m_startTime);
  6186. }
  6187. inline const struct timeval* PerformanceTrackingData::endTime() const
  6188. {
  6189. return const_cast<const struct timeval*>(&m_performanceTracker->m_endTime);
  6190. }
  6191. inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const
  6192. {
  6193. return const_cast<const struct timeval*>(&m_performanceTracker->m_lastCheckpointTime);
  6194. }
  6195. inline const std::string& PerformanceTrackingData::loggerId(void) const
  6196. {
  6197. return m_performanceTracker->m_loggerId;
  6198. }
  6199. namespace base {
  6200. /// @brief Contains some internal debugging tools like crash handler and stack tracer
  6201. namespace debug {
  6202. class StackTrace : base::NoCopy
  6203. {
  6204. public:
  6205. static const std::size_t kMaxStack = 64;
  6206. static const std::size_t kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew()
  6207. class StackTraceEntry
  6208. {
  6209. public:
  6210. StackTraceEntry(std::size_t index, const char* loc, const char* demang, const char* hex, const char* addr)
  6211. {
  6212. m_index = index;
  6213. m_location = std::string(loc);
  6214. m_demangled = std::string(demang);
  6215. m_hex = std::string(hex);
  6216. m_addr = std::string(addr);
  6217. }
  6218. StackTraceEntry(std::size_t index, char* loc)
  6219. {
  6220. m_index = index;
  6221. m_location = std::string(loc);
  6222. }
  6223. std::size_t m_index;
  6224. std::string m_location;
  6225. std::string m_demangled;
  6226. std::string m_hex;
  6227. std::string m_addr;
  6228. friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si)
  6229. {
  6230. ss << "[" << si.m_index << "] " << si.m_location << (si.m_demangled.empty() ? "" : ":") << si.m_demangled
  6231. << (si.m_hex.empty() ? "" : "+") << si.m_hex << si.m_addr;
  6232. return ss;
  6233. }
  6234. private:
  6235. StackTraceEntry(void);
  6236. };
  6237. StackTrace(void)
  6238. {
  6239. generateNew();
  6240. }
  6241. virtual ~StackTrace(void)
  6242. {
  6243. }
  6244. inline std::vector<StackTraceEntry>& getLatestStack(void)
  6245. {
  6246. return m_stack;
  6247. }
  6248. friend inline std::ostream& operator<<(std::ostream& os, const StackTrace& st)
  6249. {
  6250. std::vector<StackTraceEntry>::const_iterator it = st.m_stack.begin();
  6251. while(it != st.m_stack.end())
  6252. {
  6253. os << " " << *it++ << "\n";
  6254. }
  6255. return os;
  6256. }
  6257. private:
  6258. std::vector<StackTraceEntry> m_stack;
  6259. void generateNew(void)
  6260. {
  6261. #if ELPP_STACKTRACE
  6262. m_stack.clear();
  6263. void* stack[kMaxStack];
  6264. std::size_t size = backtrace(stack, kMaxStack);
  6265. char** strings = backtrace_symbols(stack, size);
  6266. if(size > kStackStart)
  6267. { // Skip StackTrace c'tor and generateNew
  6268. for(std::size_t i = kStackStart; i < size; ++i)
  6269. {
  6270. char* mangName = nullptr;
  6271. char* hex = nullptr;
  6272. char* addr = nullptr;
  6273. for(char* c = strings[i]; *c; ++c)
  6274. {
  6275. switch(*c)
  6276. {
  6277. case '(':
  6278. mangName = c;
  6279. break;
  6280. case '+':
  6281. hex = c;
  6282. break;
  6283. case ')':
  6284. addr = c;
  6285. break;
  6286. }
  6287. }
  6288. // Perform demangling if parsed properly
  6289. if(mangName != nullptr && hex != nullptr && addr != nullptr && mangName < hex)
  6290. {
  6291. *mangName++ = '\0';
  6292. *hex++ = '\0';
  6293. *addr++ = '\0';
  6294. int status = 0;
  6295. char* demangName = abi::__cxa_demangle(mangName, 0, 0, &status);
  6296. // if demangling is successful, output the demangled function name
  6297. if(status == 0)
  6298. {
  6299. // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html)
  6300. StackTraceEntry entry(i - 1, strings[i], demangName, hex, addr);
  6301. m_stack.push_back(entry);
  6302. }
  6303. else
  6304. {
  6305. // Not successful - we will use mangled name
  6306. StackTraceEntry entry(i - 1, strings[i], mangName, hex, addr);
  6307. m_stack.push_back(entry);
  6308. }
  6309. free(demangName);
  6310. }
  6311. else
  6312. {
  6313. StackTraceEntry entry(i - 1, strings[i]);
  6314. m_stack.push_back(entry);
  6315. }
  6316. }
  6317. }
  6318. free(strings);
  6319. #else
  6320. ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler");
  6321. #endif // ELPP_STACKTRACE
  6322. }
  6323. };
  6324. static std::string crashReason(int sig)
  6325. {
  6326. std::stringstream ss;
  6327. bool foundReason = false;
  6328. for(int i = 0; i < base::consts::kCrashSignalsCount; ++i)
  6329. {
  6330. if(base::consts::kCrashSignals[i].numb == sig)
  6331. {
  6332. ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal";
  6333. if(ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason))
  6334. {
  6335. ss << std::endl <<
  6336. " " << base::consts::kCrashSignals[i].brief << std::endl <<
  6337. " " << base::consts::kCrashSignals[i].detail;
  6338. }
  6339. foundReason = true;
  6340. }
  6341. }
  6342. if(!foundReason)
  6343. {
  6344. ss << "Application has crashed due to unknown signal [" << sig << "]";
  6345. }
  6346. return ss.str();
  6347. }
  6348. /// @brief Logs reason of crash from sig
  6349. static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger)
  6350. {
  6351. std::stringstream ss;
  6352. ss << "CRASH HANDLED; ";
  6353. ss << crashReason(sig);
  6354. #if ELPP_STACKTRACE
  6355. if(stackTraceIfAvailable)
  6356. {
  6357. ss << std::endl << " ======= Backtrace: =========" << std::endl << base::debug::StackTrace();
  6358. }
  6359. #else
  6360. ELPP_UNUSED(stackTraceIfAvailable);
  6361. #endif // ELPP_STACKTRACE
  6362. ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str();
  6363. }
  6364. static inline void crashAbort(int sig)
  6365. {
  6366. base::utils::abort(sig);
  6367. }
  6368. /// @brief Default application crash handler
  6369. ///
  6370. /// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program.
  6371. static inline void defaultCrashHandler(int sig)
  6372. {
  6373. base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId);
  6374. base::debug::crashAbort(sig);
  6375. }
  6376. /// @brief Handles unexpected crashes
  6377. class CrashHandler : base::NoCopy
  6378. {
  6379. public:
  6380. typedef void (*Handler)(int);
  6381. explicit CrashHandler(bool useDefault)
  6382. {
  6383. if(useDefault)
  6384. {
  6385. setHandler(defaultCrashHandler);
  6386. }
  6387. }
  6388. explicit CrashHandler(const Handler& cHandler)
  6389. {
  6390. setHandler(cHandler);
  6391. }
  6392. void setHandler(const Handler& cHandler)
  6393. {
  6394. m_handler = cHandler;
  6395. #if defined(ELPP_HANDLE_SIGABRT)
  6396. int i = 0; // SIGABRT is at base::consts::kCrashSignals[0]
  6397. #else
  6398. int i = 1;
  6399. #endif // defined(ELPP_HANDLE_SIGABRT)
  6400. for(; i < base::consts::kCrashSignalsCount; ++i)
  6401. {
  6402. m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler);
  6403. }
  6404. }
  6405. private:
  6406. Handler m_handler;
  6407. };
  6408. } // namespace debug
  6409. } // namespace base
  6410. extern base::debug::CrashHandler elCrashHandler;
  6411. #define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \
  6412. el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance)
  6413. /// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor
  6414. class SysLogInitializer
  6415. {
  6416. public:
  6417. SysLogInitializer(const char* processIdent, int options = 0, int facility = 0)
  6418. {
  6419. #if defined(ELPP_SYSLOG)
  6420. openlog(processIdent, options, facility);
  6421. #else
  6422. ELPP_UNUSED(processIdent);
  6423. ELPP_UNUSED(options);
  6424. ELPP_UNUSED(facility);
  6425. #endif // defined(ELPP_SYSLOG)
  6426. }
  6427. virtual ~SysLogInitializer(void)
  6428. {
  6429. #if defined(ELPP_SYSLOG)
  6430. closelog();
  6431. #endif // defined(ELPP_SYSLOG)
  6432. }
  6433. };
  6434. #define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac)
  6435. /// @brief Static helpers for developers
  6436. class Helpers : base::StaticClass
  6437. {
  6438. public:
  6439. /// @brief Shares logging repository (base::Storage)
  6440. static inline void setStorage(base::type::StoragePointer storage)
  6441. {
  6442. ELPP = storage;
  6443. }
  6444. /// @return Main storage repository
  6445. static inline base::type::StoragePointer storage()
  6446. {
  6447. return ELPP;
  6448. }
  6449. /// @brief Sets application arguments and figures out whats active for logging and whats not.
  6450. static inline void setArgs(int argc, char** argv)
  6451. {
  6452. ELPP->setApplicationArguments(argc, argv);
  6453. }
  6454. /// @copydoc setArgs(int argc, char** argv)
  6455. static inline void setArgs(int argc, const char** argv)
  6456. {
  6457. ELPP->setApplicationArguments(argc, const_cast<char**>(argv));
  6458. }
  6459. /// @brief Overrides default crash handler and installs custom handler.
  6460. /// @param crashHandler A functor with no return type that takes single int argument.
  6461. /// Handler is a typedef with specification: void (*Handler)(int)
  6462. static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler)
  6463. {
  6464. el::elCrashHandler.setHandler(crashHandler);
  6465. }
  6466. /// @brief Abort due to crash with signal in parameter
  6467. /// @param sig Crash signal
  6468. static inline void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0)
  6469. {
  6470. std::stringstream ss;
  6471. ss << base::debug::crashReason(sig).c_str();
  6472. ss << " - [Called el::Helpers::crashAbort(" << sig << ")]";
  6473. if(sourceFile != nullptr && strlen(sourceFile) > 0)
  6474. {
  6475. ss << " - Source: " << sourceFile;
  6476. if(line > 0)
  6477. ss << ":" << line;
  6478. else
  6479. ss << " (line number not specified)";
  6480. }
  6481. base::utils::abort(sig, ss.str());
  6482. }
  6483. /// @brief Logs reason of crash as per sig
  6484. /// @param sig Crash signal
  6485. /// @param stackTraceIfAvailable Includes stack trace if available
  6486. /// @param level Logging level
  6487. /// @param logger Logger to use for logging
  6488. static inline void logCrashReason(int sig, bool stackTraceIfAvailable = false,
  6489. Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId)
  6490. {
  6491. el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger);
  6492. }
  6493. /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out
  6494. /// (can be useful for backing up)
  6495. static inline void installPreRollOutCallback(const PreRollOutCallback& callback)
  6496. {
  6497. ELPP->setPreRollOutCallback(callback);
  6498. }
  6499. /// @brief Uninstalls pre rollout callback
  6500. static inline void uninstallPreRollOutCallback(void)
  6501. {
  6502. ELPP->unsetPreRollOutCallback();
  6503. }
  6504. /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched
  6505. template <typename T>
  6506. static inline bool installLogDispatchCallback(const std::string& id)
  6507. {
  6508. return ELPP->installLogDispatchCallback<T>(id);
  6509. }
  6510. /// @brief Uninstalls log dispatch callback
  6511. template <typename T>
  6512. static inline void uninstallLogDispatchCallback(const std::string& id)
  6513. {
  6514. ELPP->uninstallLogDispatchCallback<T>(id);
  6515. }
  6516. template <typename T>
  6517. static inline T* logDispatchCallback(const std::string& id)
  6518. {
  6519. return ELPP->logDispatchCallback<T>(id);
  6520. }
  6521. /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished
  6522. template <typename T>
  6523. static inline bool installPerformanceTrackingCallback(const std::string& id)
  6524. {
  6525. return ELPP->installPerformanceTrackingCallback<T>(id);
  6526. }
  6527. /// @brief Uninstalls post performance tracking handler
  6528. template <typename T>
  6529. static inline void uninstallPerformanceTrackingCallback(const std::string& id)
  6530. {
  6531. ELPP->uninstallPerformanceTrackingCallback<T>(id);
  6532. }
  6533. template <typename T>
  6534. static inline T* performanceTrackingCallback(const std::string& id)
  6535. {
  6536. return ELPP->performanceTrackingCallback<T>(id);
  6537. }
  6538. /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const
  6539. template <typename T>
  6540. static std::string convertTemplateToStdString(const T& templ)
  6541. {
  6542. el::Logger* logger =
  6543. ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId);
  6544. if(logger == nullptr)
  6545. {
  6546. return std::string();
  6547. }
  6548. base::MessageBuilder b;
  6549. b.initialize(logger);
  6550. logger->acquireLock();
  6551. b << templ;
  6552. #if defined(ELPP_UNICODE)
  6553. std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end());
  6554. #else
  6555. std::string s = logger->stream().str();
  6556. #endif // defined(ELPP_UNICODE)
  6557. logger->stream().str(ELPP_LITERAL(""));
  6558. logger->releaseLock();
  6559. return s;
  6560. }
  6561. /// @brief Returns command line arguments (pointer) provided to easylogging++
  6562. static inline const el::base::utils::CommandLineArgs* commandLineArgs(void)
  6563. {
  6564. return ELPP->commandLineArgs();
  6565. }
  6566. /// @brief Installs user defined format specifier and handler
  6567. static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier)
  6568. {
  6569. ELPP->installCustomFormatSpecifier(customFormatSpecifier);
  6570. }
  6571. /// @brief Uninstalls user defined format specifier and handler
  6572. static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier)
  6573. {
  6574. return ELPP->uninstallCustomFormatSpecifier(formatSpecifier);
  6575. }
  6576. /// @brief Returns true if custom format specifier is installed
  6577. static inline bool hasCustomFormatSpecifier(const char* formatSpecifier)
  6578. {
  6579. return ELPP->hasCustomFormatSpecifier(formatSpecifier);
  6580. }
  6581. static inline void validateFileRolling(Logger* logger, Level level)
  6582. {
  6583. if(logger == nullptr) return;
  6584. logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback());
  6585. }
  6586. };
  6587. /// @brief Static helpers to deal with loggers and their configurations
  6588. class Loggers : base::StaticClass
  6589. {
  6590. public:
  6591. /// @brief Gets existing or registers new logger
  6592. static inline Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true)
  6593. {
  6594. base::threading::ScopedLock scopedLock(ELPP->lock());
  6595. return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable);
  6596. }
  6597. /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister
  6598. /// loggers initialized / used by third-party libs.
  6599. static inline bool unregisterLogger(const std::string& identity)
  6600. {
  6601. base::threading::ScopedLock scopedLock(ELPP->lock());
  6602. return ELPP->registeredLoggers()->remove(identity);
  6603. }
  6604. /// @brief Whether or not logger with id is registered
  6605. static inline bool hasLogger(const std::string& identity)
  6606. {
  6607. base::threading::ScopedLock scopedLock(ELPP->lock());
  6608. return ELPP->registeredLoggers()->has(identity);
  6609. }
  6610. /// @brief Reconfigures specified logger with new configurations
  6611. static inline Logger* reconfigureLogger(Logger* logger, const Configurations& configurations)
  6612. {
  6613. if(!logger) return nullptr;
  6614. logger->configure(configurations);
  6615. return logger;
  6616. }
  6617. /// @brief Reconfigures logger with new configurations after looking it up using identity
  6618. static inline Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations)
  6619. {
  6620. return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations);
  6621. }
  6622. /// @brief Reconfigures logger's single configuration
  6623. static inline Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType,
  6624. const std::string& value)
  6625. {
  6626. Logger* logger = Loggers::getLogger(identity);
  6627. if(logger == nullptr)
  6628. {
  6629. return nullptr;
  6630. }
  6631. logger->configurations()->set(Level::Global, configurationType, value);
  6632. logger->reconfigure();
  6633. return logger;
  6634. }
  6635. /// @brief Reconfigures all the existing loggers with new configurations
  6636. static inline void reconfigureAllLoggers(const Configurations& configurations)
  6637. {
  6638. for(base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin();
  6639. it != ELPP->registeredLoggers()->end(); ++it)
  6640. {
  6641. Loggers::reconfigureLogger(it->second, configurations);
  6642. }
  6643. }
  6644. /// @brief Reconfigures single configuration for all the loggers
  6645. static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value)
  6646. {
  6647. reconfigureAllLoggers(Level::Global, configurationType, value);
  6648. }
  6649. /// @brief Reconfigures single configuration for all the loggers for specified level
  6650. static inline void reconfigureAllLoggers(Level level, ConfigurationType configurationType,
  6651. const std::string& value)
  6652. {
  6653. for(base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin();
  6654. it != ELPP->registeredLoggers()->end(); ++it)
  6655. {
  6656. Logger* logger = it->second;
  6657. logger->configurations()->set(level, configurationType, value);
  6658. logger->reconfigure();
  6659. }
  6660. }
  6661. /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers
  6662. static inline void setDefaultConfigurations(const Configurations& configurations, bool reconfigureExistingLoggers = false)
  6663. {
  6664. ELPP->registeredLoggers()->setDefaultConfigurations(configurations);
  6665. if(reconfigureExistingLoggers)
  6666. {
  6667. Loggers::reconfigureAllLoggers(configurations);
  6668. }
  6669. }
  6670. /// @brief Returns current default
  6671. static inline const Configurations* defaultConfigurations(void)
  6672. {
  6673. return ELPP->registeredLoggers()->defaultConfigurations();
  6674. }
  6675. /// @brief Returns log stream reference pointer if needed by user
  6676. static inline const base::LogStreamsReferenceMap* logStreamsReference(void)
  6677. {
  6678. return ELPP->registeredLoggers()->logStreamsReference();
  6679. }
  6680. /// @brief Default typed configuration based on existing defaultConf
  6681. static base::TypedConfigurations defaultTypedConfigurations(void)
  6682. {
  6683. return base::TypedConfigurations(
  6684. ELPP->registeredLoggers()->defaultConfigurations(),
  6685. ELPP->registeredLoggers()->logStreamsReference());
  6686. }
  6687. /// @brief Populates all logger IDs in current repository.
  6688. /// @param [out] targetList List of fill up.
  6689. static inline std::vector<std::string>* populateAllLoggerIds(std::vector<std::string>* targetList)
  6690. {
  6691. targetList->clear();
  6692. for(base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin();
  6693. it != ELPP->registeredLoggers()->list().end(); ++it)
  6694. {
  6695. targetList->push_back(it->first);
  6696. }
  6697. return targetList;
  6698. }
  6699. /// @brief Sets configurations from global configuration file.
  6700. static void configureFromGlobal(const char* globalConfigurationFilePath)
  6701. {
  6702. std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in);
  6703. ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath
  6704. << "] for parsing.");
  6705. std::string line = std::string();
  6706. std::stringstream ss;
  6707. Logger* logger = nullptr;
  6708. auto configure = [&](void)
  6709. {
  6710. ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" << ss.str()
  6711. << "\n--------------");
  6712. Configurations c;
  6713. c.parseFromText(ss.str());
  6714. logger->configure(c);
  6715. };
  6716. while(gcfStream.good())
  6717. {
  6718. std::getline(gcfStream, line);
  6719. ELPP_INTERNAL_INFO(1, "Parsing line: " << line);
  6720. base::utils::Str::trim(line);
  6721. if(Configurations::Parser::isComment(line)) continue;
  6722. Configurations::Parser::ignoreComments(&line);
  6723. base::utils::Str::trim(line);
  6724. if(line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId)))
  6725. {
  6726. if(!ss.str().empty() && logger != nullptr)
  6727. {
  6728. configure();
  6729. }
  6730. ss.str(std::string(""));
  6731. line = line.substr(2);
  6732. base::utils::Str::trim(line);
  6733. if(line.size() > 1)
  6734. {
  6735. ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'");
  6736. logger = getLogger(line);
  6737. }
  6738. }
  6739. else
  6740. {
  6741. ss << line << "\n";
  6742. }
  6743. }
  6744. if(!ss.str().empty() && logger != nullptr)
  6745. {
  6746. configure();
  6747. }
  6748. }
  6749. /// @brief Configures loggers using command line arg. Ensure you have already set command line args,
  6750. /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger.
  6751. /// If true is returned that does not mean it has been configured successfully, it only means that it
  6752. /// has attempeted to configure logger using configuration file provided in argument
  6753. static inline bool configureFromArg(const char* argKey)
  6754. {
  6755. #if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS)
  6756. ELPP_UNUSED(argKey);
  6757. #else
  6758. if(!Helpers::commandLineArgs()->hasParamWithValue(argKey))
  6759. {
  6760. return false;
  6761. }
  6762. configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey));
  6763. #endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS)
  6764. return true;
  6765. }
  6766. /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered
  6767. static inline void flushAll(void)
  6768. {
  6769. ELPP->registeredLoggers()->flushAll();
  6770. }
  6771. /// @brief Adds logging flag used internally.
  6772. static inline void addFlag(LoggingFlag flag)
  6773. {
  6774. ELPP->addFlag(flag);
  6775. }
  6776. /// @brief Removes logging flag used internally.
  6777. static inline void removeFlag(LoggingFlag flag)
  6778. {
  6779. ELPP->removeFlag(flag);
  6780. }
  6781. /// @brief Determines whether or not certain flag is active
  6782. static inline bool hasFlag(LoggingFlag flag)
  6783. {
  6784. return ELPP->hasFlag(flag);
  6785. }
  6786. /// @brief Adds flag and removes it when scope goes out
  6787. class ScopedAddFlag
  6788. {
  6789. public:
  6790. ScopedAddFlag(LoggingFlag flag) : m_flag(flag)
  6791. {
  6792. Loggers::addFlag(m_flag);
  6793. }
  6794. ~ScopedAddFlag(void)
  6795. {
  6796. Loggers::removeFlag(m_flag);
  6797. }
  6798. private:
  6799. LoggingFlag m_flag;
  6800. };
  6801. /// @brief Removes flag and add it when scope goes out
  6802. class ScopedRemoveFlag
  6803. {
  6804. public:
  6805. ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag)
  6806. {
  6807. Loggers::removeFlag(m_flag);
  6808. }
  6809. ~ScopedRemoveFlag(void)
  6810. {
  6811. Loggers::addFlag(m_flag);
  6812. }
  6813. private:
  6814. LoggingFlag m_flag;
  6815. };
  6816. /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging)
  6817. static inline void setLoggingLevel(Level level)
  6818. {
  6819. ELPP->setLoggingLevel(level);
  6820. }
  6821. /// @brief Sets verbose level on the fly
  6822. static inline void setVerboseLevel(base::type::VerboseLevel level)
  6823. {
  6824. ELPP->vRegistry()->setLevel(level);
  6825. }
  6826. /// @brief Gets current verbose level
  6827. static inline base::type::VerboseLevel verboseLevel(void)
  6828. {
  6829. return ELPP->vRegistry()->level();
  6830. }
  6831. /// @brief Sets vmodules as specified (on the fly)
  6832. static inline void setVModules(const char* modules)
  6833. {
  6834. if(ELPP->vRegistry()->vModulesEnabled())
  6835. {
  6836. ELPP->vRegistry()->setModules(modules);
  6837. }
  6838. }
  6839. /// @brief Clears vmodules
  6840. static inline void clearVModules(void)
  6841. {
  6842. ELPP->vRegistry()->clearModules();
  6843. }
  6844. };
  6845. class VersionInfo : base::StaticClass
  6846. {
  6847. public:
  6848. /// @brief Current version number
  6849. static inline const std::string version(void)
  6850. {
  6851. return std::string("9.80");
  6852. }
  6853. /// @brief Release date of current version
  6854. static inline const std::string releaseDate(void)
  6855. {
  6856. return std::string("08-01-2015 0850hrs");
  6857. }
  6858. };
  6859. } // namespace el
  6860. #undef VLOG_IS_ON
  6861. /// @brief Determines whether verbose logging is on for specified level current file.
  6862. #define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__))
  6863. #undef TIMED_BLOCK
  6864. #undef TIMED_SCOPE
  6865. #undef TIMED_FUNC
  6866. #undef ELPP_MIN_UNIT
  6867. #if defined(ELPP_PERFORMANCE_MICROSECONDS)
  6868. # define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond
  6869. #else
  6870. # define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond
  6871. #endif // (defined(ELPP_PERFORMANCE_MICROSECONDS))
  6872. /// @brief Performance tracked scope. Performance gets written when goes out of scope using
  6873. /// 'performance' logger.
  6874. ///
  6875. /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint();
  6876. /// @see el::base::PerformanceTracker
  6877. /// @see el::base::PerformanceTracker::checkpoint
  6878. // Note: Do not surround this definition with null macro because of obj instance
  6879. #define TIMED_SCOPE(obj, blockname) el::base::PerformanceTracker obj(blockname, ELPP_MIN_UNIT)
  6880. #define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::PerformanceTracker timer; } obj = { 0, \
  6881. el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT) }; obj.i < 1; ++obj.i)
  6882. /// @brief Performance tracked function. Performance gets written when goes out of scope using
  6883. /// 'performance' logger.
  6884. ///
  6885. /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint();
  6886. /// @see el::base::PerformanceTracker
  6887. /// @see el::base::PerformanceTracker::checkpoint
  6888. #define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC)
  6889. #undef PERFORMANCE_CHECKPOINT
  6890. #undef PERFORMANCE_CHECKPOINT_WITH_ID
  6891. #define PERFORMANCE_CHECKPOINT(obj) obj.checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC)
  6892. #define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj.checkpoint(id, __FILE__, __LINE__, ELPP_FUNC)
  6893. #undef ELPP_COUNTER
  6894. #undef ELPP_COUNTER_POS
  6895. /// @brief Gets hit counter for file/line
  6896. #define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__))
  6897. /// @brief Gets hit counter position for file/line, -1 if not registered yet
  6898. #define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts())
  6899. // Undef levels to support LOG(LEVEL)
  6900. #undef INFO
  6901. #undef WARNING
  6902. #undef DEBUG
  6903. #undef ERROR
  6904. #undef FATAL
  6905. #undef TRACE
  6906. #undef VERBOSE
  6907. // Undef existing
  6908. #undef CINFO
  6909. #undef CWARNING
  6910. #undef CDEBUG
  6911. #undef CFATAL
  6912. #undef CERROR
  6913. #undef CTRACE
  6914. #undef CVERBOSE
  6915. #undef CINFO_IF
  6916. #undef CWARNING_IF
  6917. #undef CDEBUG_IF
  6918. #undef CERROR_IF
  6919. #undef CFATAL_IF
  6920. #undef CTRACE_IF
  6921. #undef CVERBOSE_IF
  6922. #undef CINFO_EVERY_N
  6923. #undef CWARNING_EVERY_N
  6924. #undef CDEBUG_EVERY_N
  6925. #undef CERROR_EVERY_N
  6926. #undef CFATAL_EVERY_N
  6927. #undef CTRACE_EVERY_N
  6928. #undef CVERBOSE_EVERY_N
  6929. #undef CINFO_AFTER_N
  6930. #undef CWARNING_AFTER_N
  6931. #undef CDEBUG_AFTER_N
  6932. #undef CERROR_AFTER_N
  6933. #undef CFATAL_AFTER_N
  6934. #undef CTRACE_AFTER_N
  6935. #undef CVERBOSE_AFTER_N
  6936. #undef CINFO_N_TIMES
  6937. #undef CWARNING_N_TIMES
  6938. #undef CDEBUG_N_TIMES
  6939. #undef CERROR_N_TIMES
  6940. #undef CFATAL_N_TIMES
  6941. #undef CTRACE_N_TIMES
  6942. #undef CVERBOSE_N_TIMES
  6943. // Normal logs
  6944. #if ELPP_INFO_LOG
  6945. # define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__)
  6946. #else
  6947. # define CINFO(writer, dispatchAction, ...) el::base::NullWriter()
  6948. #endif // ELPP_INFO_LOG
  6949. #if ELPP_WARNING_LOG
  6950. # define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__)
  6951. #else
  6952. # define CWARNING(writer, dispatchAction, ...) el::base::NullWriter()
  6953. #endif // ELPP_WARNING_LOG
  6954. #if ELPP_DEBUG_LOG
  6955. # define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__)
  6956. #else
  6957. # define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter()
  6958. #endif // ELPP_DEBUG_LOG
  6959. #if ELPP_ERROR_LOG
  6960. # define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__)
  6961. #else
  6962. # define CERROR(writer, dispatchAction, ...) el::base::NullWriter()
  6963. #endif // ELPP_ERROR_LOG
  6964. #if ELPP_FATAL_LOG
  6965. # define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__)
  6966. #else
  6967. # define CFATAL(writer, dispatchAction, ...) el::base::NullWriter()
  6968. #endif // ELPP_FATAL_LOG
  6969. #if ELPP_TRACE_LOG
  6970. # define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__)
  6971. #else
  6972. # define CTRACE(writer, dispatchAction, ...) el::base::NullWriter()
  6973. #endif // ELPP_TRACE_LOG
  6974. #if ELPP_VERBOSE_LOG
  6975. # define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\
  6976. el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  6977. #else
  6978. # define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter()
  6979. #endif // ELPP_VERBOSE_LOG
  6980. // Conditional logs
  6981. #if ELPP_INFO_LOG
  6982. # define CINFO_IF(writer, condition_, dispatchAction, ...) \
  6983. ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__)
  6984. #else
  6985. # define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter()
  6986. #endif // ELPP_INFO_LOG
  6987. #if ELPP_WARNING_LOG
  6988. # define CWARNING_IF(writer, condition_, dispatchAction, ...)\
  6989. ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__)
  6990. #else
  6991. # define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter()
  6992. #endif // ELPP_WARNING_LOG
  6993. #if ELPP_DEBUG_LOG
  6994. # define CDEBUG_IF(writer, condition_, dispatchAction, ...)\
  6995. ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__)
  6996. #else
  6997. # define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter()
  6998. #endif // ELPP_DEBUG_LOG
  6999. #if ELPP_ERROR_LOG
  7000. # define CERROR_IF(writer, condition_, dispatchAction, ...)\
  7001. ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__)
  7002. #else
  7003. # define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter()
  7004. #endif // ELPP_ERROR_LOG
  7005. #if ELPP_FATAL_LOG
  7006. # define CFATAL_IF(writer, condition_, dispatchAction, ...)\
  7007. ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__)
  7008. #else
  7009. # define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter()
  7010. #endif // ELPP_FATAL_LOG
  7011. #if ELPP_TRACE_LOG
  7012. # define CTRACE_IF(writer, condition_, dispatchAction, ...)\
  7013. ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__)
  7014. #else
  7015. # define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter()
  7016. #endif // ELPP_TRACE_LOG
  7017. #if ELPP_VERBOSE_LOG
  7018. # define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \
  7019. el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
  7020. #else
  7021. # define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter()
  7022. #endif // ELPP_VERBOSE_LOG
  7023. // Occasional logs
  7024. #if ELPP_INFO_LOG
  7025. # define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\
  7026. ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__)
  7027. #else
  7028. # define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter()
  7029. #endif // ELPP_INFO_LOG
  7030. #if ELPP_WARNING_LOG
  7031. # define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\
  7032. ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__)
  7033. #else
  7034. # define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter()
  7035. #endif // ELPP_WARNING_LOG
  7036. #if ELPP_DEBUG_LOG
  7037. # define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\
  7038. ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__)
  7039. #else
  7040. # define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter()
  7041. #endif // ELPP_DEBUG_LOG
  7042. #if ELPP_ERROR_LOG
  7043. # define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\
  7044. ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__)
  7045. #else
  7046. # define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter()
  7047. #endif // ELPP_ERROR_LOG
  7048. #if ELPP_FATAL_LOG
  7049. # define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\
  7050. ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__)
  7051. #else
  7052. # define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter()
  7053. #endif // ELPP_FATAL_LOG
  7054. #if ELPP_TRACE_LOG
  7055. # define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\
  7056. ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__)
  7057. #else
  7058. # define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter()
  7059. #endif // ELPP_TRACE_LOG
  7060. #if ELPP_VERBOSE_LOG
  7061. # define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\
  7062. CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__)
  7063. #else
  7064. # define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter()
  7065. #endif // ELPP_VERBOSE_LOG
  7066. // After N logs
  7067. #if ELPP_INFO_LOG
  7068. # define CINFO_AFTER_N(writer, n, dispatchAction, ...)\
  7069. ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__)
  7070. #else
  7071. # define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter()
  7072. #endif // ELPP_INFO_LOG
  7073. #if ELPP_WARNING_LOG
  7074. # define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\
  7075. ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__)
  7076. #else
  7077. # define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter()
  7078. #endif // ELPP_WARNING_LOG
  7079. #if ELPP_DEBUG_LOG
  7080. # define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\
  7081. ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__)
  7082. #else
  7083. # define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter()
  7084. #endif // ELPP_DEBUG_LOG
  7085. #if ELPP_ERROR_LOG
  7086. # define CERROR_AFTER_N(writer, n, dispatchAction, ...)\
  7087. ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__)
  7088. #else
  7089. # define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter()
  7090. #endif // ELPP_ERROR_LOG
  7091. #if ELPP_FATAL_LOG
  7092. # define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\
  7093. ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__)
  7094. #else
  7095. # define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter()
  7096. #endif // ELPP_FATAL_LOG
  7097. #if ELPP_TRACE_LOG
  7098. # define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\
  7099. ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__)
  7100. #else
  7101. # define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter()
  7102. #endif // ELPP_TRACE_LOG
  7103. #if ELPP_VERBOSE_LOG
  7104. # define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\
  7105. CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__)
  7106. #else
  7107. # define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter()
  7108. #endif // ELPP_VERBOSE_LOG
  7109. // N Times logs
  7110. #if ELPP_INFO_LOG
  7111. # define CINFO_N_TIMES(writer, n, dispatchAction, ...)\
  7112. ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__)
  7113. #else
  7114. # define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter()
  7115. #endif // ELPP_INFO_LOG
  7116. #if ELPP_WARNING_LOG
  7117. # define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\
  7118. ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__)
  7119. #else
  7120. # define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter()
  7121. #endif // ELPP_WARNING_LOG
  7122. #if ELPP_DEBUG_LOG
  7123. # define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\
  7124. ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__)
  7125. #else
  7126. # define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter()
  7127. #endif // ELPP_DEBUG_LOG
  7128. #if ELPP_ERROR_LOG
  7129. # define CERROR_N_TIMES(writer, n, dispatchAction, ...)\
  7130. ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__)
  7131. #else
  7132. # define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter()
  7133. #endif // ELPP_ERROR_LOG
  7134. #if ELPP_FATAL_LOG
  7135. # define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\
  7136. ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__)
  7137. #else
  7138. # define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter()
  7139. #endif // ELPP_FATAL_LOG
  7140. #if ELPP_TRACE_LOG
  7141. # define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\
  7142. ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__)
  7143. #else
  7144. # define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter()
  7145. #endif // ELPP_TRACE_LOG
  7146. #if ELPP_VERBOSE_LOG
  7147. # define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\
  7148. CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__)
  7149. #else
  7150. # define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter()
  7151. #endif // ELPP_VERBOSE_LOG
  7152. //
  7153. // Custom Loggers - Requires (level, dispatchAction, loggerId/s)
  7154. //
  7155. // undef existing
  7156. #undef CLOG
  7157. #undef CLOG_VERBOSE
  7158. #undef CVLOG
  7159. #undef CLOG_IF
  7160. #undef CLOG_VERBOSE_IF
  7161. #undef CVLOG_IF
  7162. #undef CLOG_EVERY_N
  7163. #undef CVLOG_EVERY_N
  7164. #undef CLOG_AFTER_N
  7165. #undef CVLOG_AFTER_N
  7166. #undef CLOG_N_TIMES
  7167. #undef CVLOG_N_TIMES
  7168. // Normal logs
  7169. #define CLOG(LEVEL, ...)\
  7170. C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7171. #define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7172. // Conditional logs
  7173. #define CLOG_IF(condition, LEVEL, ...)\
  7174. C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7175. #define CVLOG_IF(condition, vlevel, ...)\
  7176. CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7177. // Hit counts based logs
  7178. #define CLOG_EVERY_N(n, LEVEL, ...)\
  7179. C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7180. #define CVLOG_EVERY_N(n, vlevel, ...)\
  7181. CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7182. #define CLOG_AFTER_N(n, LEVEL, ...)\
  7183. C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7184. #define CVLOG_AFTER_N(n, vlevel, ...)\
  7185. CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7186. #define CLOG_N_TIMES(n, LEVEL, ...)\
  7187. C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7188. #define CVLOG_N_TIMES(n, vlevel, ...)\
  7189. CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7190. //
  7191. // Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros
  7192. //
  7193. // undef existing
  7194. #undef LOG
  7195. #undef VLOG
  7196. #undef LOG_IF
  7197. #undef VLOG_IF
  7198. #undef LOG_EVERY_N
  7199. #undef VLOG_EVERY_N
  7200. #undef LOG_AFTER_N
  7201. #undef VLOG_AFTER_N
  7202. #undef LOG_N_TIMES
  7203. #undef VLOG_N_TIMES
  7204. #undef ELPP_CURR_FILE_LOGGER_ID
  7205. #if defined(ELPP_DEFAULT_LOGGER)
  7206. # define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER
  7207. #else
  7208. # define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId
  7209. #endif
  7210. #undef ELPP_TRACE
  7211. #define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID)
  7212. // Normal logs
  7213. #define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7214. #define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7215. // Conditional logs
  7216. #define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7217. #define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7218. // Hit counts based logs
  7219. #define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7220. #define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7221. #define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7222. #define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7223. #define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7224. #define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7225. // Generic PLOG()
  7226. #undef CPLOG
  7227. #undef CPLOG_IF
  7228. #undef PLOG
  7229. #undef PLOG_IF
  7230. #undef DCPLOG
  7231. #undef DCPLOG_IF
  7232. #undef DPLOG
  7233. #undef DPLOG_IF
  7234. #define CPLOG(LEVEL, ...)\
  7235. C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7236. #define CPLOG_IF(condition, LEVEL, ...)\
  7237. C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7238. #define DCPLOG(LEVEL, ...)\
  7239. if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7240. #define DCPLOG_IF(condition, LEVEL, ...)\
  7241. C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__)
  7242. #define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7243. #define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7244. #define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7245. #define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7246. // Generic SYSLOG()
  7247. #undef CSYSLOG
  7248. #undef CSYSLOG_IF
  7249. #undef CSYSLOG_EVERY_N
  7250. #undef CSYSLOG_AFTER_N
  7251. #undef CSYSLOG_N_TIMES
  7252. #undef SYSLOG
  7253. #undef SYSLOG_IF
  7254. #undef SYSLOG_EVERY_N
  7255. #undef SYSLOG_AFTER_N
  7256. #undef SYSLOG_N_TIMES
  7257. #undef DCSYSLOG
  7258. #undef DCSYSLOG_IF
  7259. #undef DCSYSLOG_EVERY_N
  7260. #undef DCSYSLOG_AFTER_N
  7261. #undef DCSYSLOG_N_TIMES
  7262. #undef DSYSLOG
  7263. #undef DSYSLOG_IF
  7264. #undef DSYSLOG_EVERY_N
  7265. #undef DSYSLOG_AFTER_N
  7266. #undef DSYSLOG_N_TIMES
  7267. #if defined(ELPP_SYSLOG)
  7268. # define CSYSLOG(LEVEL, ...)\
  7269. C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7270. # define CSYSLOG_IF(condition, LEVEL, ...)\
  7271. C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7272. # define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7273. # define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7274. # define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7275. # define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId)
  7276. # define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId)
  7277. # define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId)
  7278. # define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId)
  7279. # define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId)
  7280. # define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7281. # define DCSYSLOG_IF(condition, LEVEL, ...)\
  7282. C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__)
  7283. # define DCSYSLOG_EVERY_N(n, LEVEL, ...)\
  7284. if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7285. # define DCSYSLOG_AFTER_N(n, LEVEL, ...)\
  7286. if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7287. # define DCSYSLOG_N_TIMES(n, LEVEL, ...)\
  7288. if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__)
  7289. # define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId)
  7290. # define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId)
  7291. # define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId)
  7292. # define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId)
  7293. # define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId)
  7294. #else
  7295. # define CSYSLOG(LEVEL, ...) el::base::NullWriter()
  7296. # define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter()
  7297. # define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter()
  7298. # define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter()
  7299. # define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter()
  7300. # define SYSLOG(LEVEL) el::base::NullWriter()
  7301. # define SYSLOG_IF(condition, LEVEL) el::base::NullWriter()
  7302. # define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter()
  7303. # define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter()
  7304. # define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter()
  7305. # define DCSYSLOG(LEVEL, ...) el::base::NullWriter()
  7306. # define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter()
  7307. # define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter()
  7308. # define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter()
  7309. # define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter()
  7310. # define DSYSLOG(LEVEL) el::base::NullWriter()
  7311. # define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter()
  7312. # define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter()
  7313. # define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter()
  7314. # define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter()
  7315. #endif // defined(ELPP_SYSLOG)
  7316. //
  7317. // Custom Debug Only Loggers - Requires (level, loggerId/s)
  7318. //
  7319. // undef existing
  7320. #undef DCLOG
  7321. #undef DCVLOG
  7322. #undef DCLOG_IF
  7323. #undef DCVLOG_IF
  7324. #undef DCLOG_EVERY_N
  7325. #undef DCVLOG_EVERY_N
  7326. #undef DCLOG_AFTER_N
  7327. #undef DCVLOG_AFTER_N
  7328. #undef DCLOG_N_TIMES
  7329. #undef DCVLOG_N_TIMES
  7330. // Normal logs
  7331. #define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__)
  7332. #define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__)
  7333. #define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__)
  7334. // Conditional logs
  7335. #define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__)
  7336. #define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__)
  7337. // Hit counts based logs
  7338. #define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__)
  7339. #define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__)
  7340. #define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__)
  7341. #define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__)
  7342. #define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__)
  7343. #define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__)
  7344. //
  7345. // Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros
  7346. //
  7347. // undef existing
  7348. #undef DLOG
  7349. #undef DVLOG
  7350. #undef DLOG_IF
  7351. #undef DVLOG_IF
  7352. #undef DLOG_EVERY_N
  7353. #undef DVLOG_EVERY_N
  7354. #undef DLOG_AFTER_N
  7355. #undef DVLOG_AFTER_N
  7356. #undef DLOG_N_TIMES
  7357. #undef DVLOG_N_TIMES
  7358. // Normal logs
  7359. #define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7360. #define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7361. // Conditional logs
  7362. #define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7363. #define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7364. // Hit counts based logs
  7365. #define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7366. #define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7367. #define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7368. #define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7369. #define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID)
  7370. #define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID)
  7371. // Check macros
  7372. #undef CCHECK
  7373. #undef CPCHECK
  7374. #undef CCHECK_EQ
  7375. #undef CCHECK_NE
  7376. #undef CCHECK_LT
  7377. #undef CCHECK_GT
  7378. #undef CCHECK_LE
  7379. #undef CCHECK_GE
  7380. #undef CCHECK_BOUNDS
  7381. #undef CCHECK_NOTNULL
  7382. #undef CCHECK_STRCASEEQ
  7383. #undef CCHECK_STRCASENE
  7384. #undef CHECK
  7385. #undef PCHECK
  7386. #undef CHECK_EQ
  7387. #undef CHECK_NE
  7388. #undef CHECK_LT
  7389. #undef CHECK_GT
  7390. #undef CHECK_LE
  7391. #undef CHECK_GE
  7392. #undef CHECK_BOUNDS
  7393. #undef CHECK_NOTNULL
  7394. #undef CHECK_STRCASEEQ
  7395. #undef CHECK_STRCASENE
  7396. #define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] "
  7397. #define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] "
  7398. #define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID)
  7399. #define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID)
  7400. #define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__)
  7401. #define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__)
  7402. #define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__)
  7403. #define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__)
  7404. #define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__)
  7405. #define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__)
  7406. #define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__)
  7407. #define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7408. #define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7409. #define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7410. #define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7411. #define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7412. #define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7413. #define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID)
  7414. namespace el {
  7415. namespace base {
  7416. namespace utils {
  7417. template <typename T>
  7418. static T* checkNotNull(T* ptr, const char* name, const char* loggers, ...)
  7419. {
  7420. CLOG_IF(ptr == nullptr, FATAL, loggers) << "Check failed: [" << name << " != nullptr]";
  7421. return ptr;
  7422. }
  7423. } // namespace utils
  7424. } // namespace base
  7425. } // namespace el
  7426. #define CCHECK_NOTNULL(ptr, ...) el::base::utils::checkNotNull(ptr, #ptr, __VA_ARGS__)
  7427. #define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \
  7428. << "Check failed: [" << #str1 << " == " << #str2 << "] "
  7429. #define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \
  7430. << "Check failed: [" << #str1 << " != " << #str2 << "] "
  7431. #define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \
  7432. << "Check failed: [" << #str1 << " == " << #str2 << "] "
  7433. #define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \
  7434. << "Check failed: [" << #str1 << " != " << #str2 << "] "
  7435. #define CHECK_NOTNULL(ptr) CCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID)
  7436. #define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7437. #define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7438. #define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7439. #define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7440. #undef DCCHECK
  7441. #undef DCCHECK_EQ
  7442. #undef DCCHECK_NE
  7443. #undef DCCHECK_LT
  7444. #undef DCCHECK_GT
  7445. #undef DCCHECK_LE
  7446. #undef DCCHECK_GE
  7447. #undef DCCHECK_BOUNDS
  7448. #undef DCCHECK_NOTNULL
  7449. #undef DCCHECK_STRCASEEQ
  7450. #undef DCCHECK_STRCASENE
  7451. #undef DCPCHECK
  7452. #undef DCHECK
  7453. #undef DCHECK_EQ
  7454. #undef DCHECK_NE
  7455. #undef DCHECK_LT
  7456. #undef DCHECK_GT
  7457. #undef DCHECK_LE
  7458. #undef DCHECK_GE
  7459. #undef DCHECK_BOUNDS_
  7460. #undef DCHECK_NOTNULL
  7461. #undef DCHECK_STRCASEEQ
  7462. #undef DCHECK_STRCASENE
  7463. #undef DPCHECK
  7464. #define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__)
  7465. #define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__)
  7466. #define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__)
  7467. #define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__)
  7468. #define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__)
  7469. #define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__)
  7470. #define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__)
  7471. #define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__)
  7472. #define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL(ptr, __VA_ARGS__)
  7473. #define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__)
  7474. #define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__)
  7475. #define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__)
  7476. #define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__)
  7477. #define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__)
  7478. #define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID)
  7479. #define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7480. #define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7481. #define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7482. #define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7483. #define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7484. #define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID)
  7485. #define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID)
  7486. #define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID)
  7487. #define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7488. #define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7489. #define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7490. #define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID)
  7491. #define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID)
  7492. #if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING)
  7493. # define ELPP_USE_DEF_CRASH_HANDLER false
  7494. #else
  7495. # define ELPP_USE_DEF_CRASH_HANDLER true
  7496. #endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING)
  7497. #define ELPP_CRASH_HANDLER_INIT
  7498. #define ELPP_INIT_EASYLOGGINGPP(val)\
  7499. ELPP_INITI_BASIC_DECLR\
  7500. namespace el {\
  7501. namespace base {\
  7502. el::base::type::StoragePointer elStorage(val);\
  7503. }\
  7504. el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\
  7505. }
  7506. #if ELPP_ASYNC_LOGGING
  7507. # define INITIALIZE_EASYLOGGINGPP\
  7508. ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\
  7509. new el::base::AsyncDispatchWorker()))\
  7510. #else
  7511. # define INITIALIZE_EASYLOGGINGPP\
  7512. ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder())))
  7513. #endif // ELPP_ASYNC_LOGGING
  7514. #define INITIALIZE_NULL_EASYLOGGINGPP\
  7515. ELPP_INITI_BASIC_DECLR\
  7516. namespace el {\
  7517. namespace base {\
  7518. el::base::type::StoragePointer elStorage;\
  7519. }\
  7520. el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\
  7521. }
  7522. // NOTE: no ELPP_INITI_BASIC_DECLR when sharing - causes double free corruption on external symbols
  7523. #define SHARE_EASYLOGGINGPP(initializedStorage)\
  7524. namespace el {\
  7525. namespace base {\
  7526. el::base::type::StoragePointer elStorage(initializedStorage);\
  7527. }\
  7528. el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\
  7529. }
  7530. #if defined(ELPP_UNICODE)
  7531. # define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale(""))
  7532. #else
  7533. # define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv)
  7534. #endif // defined(ELPP_UNICODE)
  7535. #endif // EASYLOGGINGPP_H