#Async Loggers
1 messages ยท Page 2 of 1
microsecond precision ๐
more or less ๐
i did some tests and actually not only DateTime.Now has more precision than Environment.TickCount but it also has a negligible difference in overhead as it uses cached values
i still left the config option to use TickCount if ever needed
@rancid parcel i pushed the changes to github but haven't made a release, tell me what you think and if you want do a couple of tests
I mean if it's a beneficial update you may as well push it lol, and then if Zaggy requests more changes just push them it sounds like this update is pretty big tbh from all the back and forth you've been having ๐
honestly I wouldn't bother if DateTime.Now is fine lol
there's a limit to the reasonableness of customization
also as long as the time is grabbed on the caller thread then it seems good to me ๐ I can't really do any thorough testing unless I play with my friends tbh
as far as the lock-free impl, I'll try to get a bit of normal gameplay with it before I decide whether it's stable
yeah time is always grabbed upstream of the enqueueing
and if a call already has a timestamp grabbed it does not update the timestamp ( so the double enqueing of unity logs uses the og timestamp )
ahh I see
I was gonna ask about that
sounds interesting
I suppose you determine that by whether the message is coming through the Unity logging event?
i use a ThreadLocal to store the current log timestamp, if the variable has a value i use the value if not i grab the currentTimestamp and put it in the variable
after the Dequeued call i reset the variable to null
gotcha, that does seem like a bit of a pain
it is necessary to keep track of the right timestamp sadly
maybe if I rework it the way I described that could be improved but we'll see if that actually functions
yeah
it works like a charm, and even better now that i moved the actual print from a wrapper to a postfix
timestamps starting as soon as the preloader starts
@pure trail could we get a pin on this? ๐ฅบ
oh I just realized I was looking at the wrong branch
I had rebased onto master earlier and was wondering why it wasn't a preloader
good idea it reminded me i have the preview tracker here too ๐
Timestamp Preview1
it is still not fully tested that's why i haven't published it yet
#modding-general message
if i remember right this kind of error is caused by MoreCompany
so tis coincidence it's between 2 LGU console stuff? . ,.
from what i can see it's during a player connecting which is a known issue of MoreCompany
#1174573561885761547 message
if in doubt, before reporting it, always test if removing the mod you think is the cause fixes the issue
so apparently the the logs that we're not catching simply pop up from nowhere ๐ they trigger the logGeneratedEvent wihtout it originating from anywhere
oh those negative collider ones?
yeah, but generally any unity log that is cauded by unity itself and not the game
i think those in particular might come from c++ land
they bypass all loggers and just get writen to disk ๐
@trail jolt spent a fat minute looking for them and i did too
well i would be intrested in fixing the BoxColliders specifically, but for Matty's Fixes not for AsyncLoggers
what matters for AsyncLoggers is that there is no way of intercepting them before they are writtend to the Player.log
yeah, after a while of looking into them, I suspect they're in the c++ code, so it's significantly harder to intercept them, you'd have to look into a harmony-esque thing for c++ & figure out how to actually view the compiled c++ code & whatnot
getting some errors here, might be this mod
#modding-general message
[19:11:25.8086130] [Error : Unity Log] IndexOutOfRangeException: Index was outside the bounds of the array.
Stack trace:
(wrapper dynamic-method) HUDManager.DMD<HUDManager::AddPlayerChatMessageClientRpc>(HUDManager,string,int)
(wrapper dynamic-method) HUDManager.DMD<HUDManager::AddPlayerChatMessageServerRpc>(HUDManager,string,int)
HUDManager.__rpc_handler_2930587515 (Unity.Netcode.NetworkBehaviour target, Unity.Netcode.FastBufferReader reader, Unity.Netcode.__RpcParams rpcParams) (at <af9b1eec498a45aebd42601d6ab85015>:0)
Unity.Netcode.RpcMessageHelpers.Handle (Unity.Netcode.NetworkContext& context, Unity.Netcode.RpcMetadata& metadata, Unity.Netcode.FastBufferReader& payload, Unity.Netcode.__RpcParams& rpcParams) (at <895801699cfc4b4ab52267f31e2a4998>:0)
Rethrow as Exception: Unhandled RPC exception!
UnityEngine.Logger:LogException(Exception, Object)
Originated from:
at UnityEngine.Debug.LogException (System.Exception exception) [0x00000] in <e27997765c1848b09d8073e5d642717a>:0
at Unity.Netcode.RpcMessageHelpers.Handle (Unity.Netcode.NetworkContext& context, Unity.Netcode.RpcMetadata& metadata, Unity.Netcode.FastBufferReader& payload, Unity.Netcode.__RpcParams& rpcParams) [0x00000] in <895801699cfc4b4ab52267f31e2a4998>:0
at Unity.Netcode.ServerRpcMessage.Handle (Unity.Netcode.NetworkContext& context) [0x00000] in <895801699cfc4b4ab52267f31e2a4998>:0
at Unity.Netcode.NetworkBehaviour.__endSendServerRpc (Unity.Netcode.FastBufferWriter& bufferWriter, System.UInt32 rpcMethodId, Unity.Netcode.ServerRpcParams serverRpcParams, Unity.Netcode.RpcDelivery rpcDelivery) [0x00000] in <895801699cfc4b4ab52267f31e2a4998>:0
at HUDManager.DMD<HUDManager::AddPlayerChatMessageServerRpc> (HUDManager , System.String , System.Int32 ) [0x00000] in <af9b1eec498a45aebd42601d6ab85015>:0
at System.Reflection.RuntimeMethodInfo.InternalInvoke (System.Reflection.RuntimeMethodInfo , System.Object , System.Object[] , System.Exception& ) [0x00000] in <787acc3c9a4c471ba7d971300105af24>:0
at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <787acc3c9a4c471ba7d971300105af24>:0
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <787acc3c9a4c471ba7d971300105af24>:0
at MoreCompany.ReflectionUtils.InvokeMethod (System.Object obj, System.String methodName, System.Object[] parameters) [0x00012] in D:\VisualStudioProjects\MoreCompany\MoreCompany\ReflectionUtils.cs:12
at MoreCompany.SendChatToServerPatch.Prefix (HUDManager __instance, System.String chatMessage, System.Int32 playerId) [0x00061] in D:\VisualStudioProjects\MoreCompany\MoreCompany\ChatPatches.cs:32
at HUDManager.DMD<HUDManager::AddTextToChatOnServer> (HUDManager , System.String , System.Int32 ) [0x00000] in <af9b1eec498a45aebd42601d6ab85015>:0
at MoreCompany.ConnectClientToPlayerObjectPatch.Postfix (GameNetcodeStuff.PlayerControllerB __instance) [0x0005d] in D:\VisualStudioProjects\MoreCompany\MoreCompany\ChatPatches.cs:74
at GameNetcodeStuff.PlayerControllerB.DMD<GameNetcodeStuff.PlayerControllerB::ConnectClientToPlayerObject> (GameNetcodeStuff.PlayerControllerB ) [0x00000] in <af9b1eec498a45aebd42601d6ab85015>:0
at GameNetcodeStuff.PlayerControllerB.DMD<GameNetcodeStuff.PlayerControllerB::Update> (GameNetcodeStuff.PlayerControllerB ) [0x00000] in <af9b1eec498a45aebd42601d6ab85015>:0
frankenstein stackTrace ๐
i'm intercepting the stacktraces unity gives to BepInEx. detecting if AsyncLogger is at the root of the stack trace, remove it from the root and attach the saved stacktrace of before the async call ๐
with Async
whithout async
Version 1.4.0
- added timestamps to BepInEx logs
- Frankenstein patch the stacktraces to hide AsyncLogger from them
๐ .
i must thank asyncloggers
for one thing that asyncloggers isnt supposed to do
displaying the win32 error that entity got
๐๐
@rancid parcel would you prefer this kind of counter as timestamp instead?
is that based on the tick count value? I think wrt using the ticks I'd prefer it to be modulo a fairly small value so it's compact
but really, a proper time format is better and I don't think there's a need for anything else
no it's a global counter atomically incremented each time a log call happens
oh, huh
I assumed it wasn't that since it skipped straight to 64 in your screenshot
i mean it's already on github, just did not feel was worth a release yet
I'm probably not going to be able to look at it for a while, but I'd like it try and hack something together to get proper ordering
ah that's fine
so many options though 
using this number you'll be 100% sure the order is correct.. each number will be unique and increasing
yeah, that's definitely good
with both ticks and date there is some cases where multiple log lines have the same timestamp
that's true I suppose
still, I don't really consider it a solution unless it's default, since I don't think I'll tend to use this mod when trying to reproduce issues
it's mainly a concern when getting logs from end users, in which case they likely won't have changed the option
i do like to use the date timestamps to figure out when something happend as normal logs dont give you an idea on how much time has passed between log lines
agreed
it definitely is handy
that's part of the reason why I think it would be nice to reformat the messages ourselves
we can put the timestamps in at the source without hacks (hopefully)
and only call string.Format once
we may make a custom diskListener to write the logs in order ๐ค
bepinex has mulitple LogListeners to write things, one is the consoleListener, one is the Disk (LogOutput.log) and one is UnityListener which writes Mod logs to unity Player.log
it's so weird to me that they're called listeners, I always think it's the thing intercepting log messages instead of writing them
it makes sens because they are listening to events, but if you do not know that, they would be better names as Writers
sure, but their purpose isn't to listen to events
what I mean is that their functionality is to write the logs to somewhere
listening is a step in the process, not the actual purpose
anyway it doesn't matter, that's just why it doesn't make sense in my head
true
@rancid parcel
what about dumping them in a sqlite db ๐
as always asynchronously to never halt the game
I have insane fps drops while scanning 17k loot on the ship after the last update with Shiploot enabled
you can try disable TimeStamps in the config but they should not be affecting anything
i've run with more than 20k of loot worth whitout any issues tho ๐ค
It didn't help
try downgrade the mod or remove it but i doubt it's caused by AsyncLogger
Ok, i'll try later
lmao I guess that's an interesting solution to the problem, but I'd imagine not a lot of people will be looking for a database instead of a log file to share
i mean i made sure to have the db file be writted in the same place of the LogOutput.log file
and called it LogOutput.sqlite ๐คฃ
pretty sure if you ask a random to grab the LogOutput they will send both of them
not too bad either way XD
what i am unsure yet is if this additional logger will affect performance tho, i made sure to have it run async but...
Wouldn't dumping the data to a simple csv file do mostly the same while still being easily readable by anyone? A db for game logs seems kinda overkill
basically, yeah
I would argue it shouldn't be necessary to add a format at all to sort the messages, but it'll take more work to write them in order by default
I would like to look into that, but I've mostly been focused on optimizing CullFactory 1.0
writing them in order would require you to keep them i nmemory and wait for the missing ones in the seqence before writing the ones you already have, and you also have to rememeber about the holes in the uuids that come from the logs that have never been printed
there is simply no feasible way of doing that with a mod without affecting performance somehow
csv would work but you already have the normal text one, and using a db allows me to log more data in less space :D
it is possible to get them in order except for the native log messages if what I'm thinking of is viable
I do need to think of a way to allow those to be included too though
but wasn't your issues exaclty that the native ones were not in order? XD
no, the UnityEngine.Debug logs
those aren't native
and actually, I suppose that the native logs would be in order, if we can differentiate them from the scripting engine logs
that is the complicated part though
From easy solutions I guess you could combine both solutions - orderby id and dump it again to log file on game exit. It would increase the quit time a little bit, but at least it would be simple and produce logs in correct order.
people often share logs from the console as well
True
basically, what I'm advocating for (and willing to put in the work for eventually) is to have this be a solution with no downsides
if I intercept the scripted log messages at the call site and then format them myself and send them to BepInEx directly, then we have no ordering issues
no keeping them in memory nor re-reading them is possible as both would affect performance which would defeat the purpose of this mod
It really wouldn't affect "performance" if it would be done only on game exit, but it wouldn't solve other issues.
well it would make the boot times longer plus you would still need to store somewhere the information to reorder them
i feel like while slighlty overkill a db works fine, but a csv could also work
๐ค with a csv you would need to import it in excel for reordering tho, but a db is even worse as you'd need an other program to read it ๐
I tested these mods (clean profile, default settings) and my game still freezes a lot when scanning, downgrading to version 1.3.0 solves the problem for me. Removing ShipLoot or AsyncLoggers also fixes this. @past cairn
the update for ShipLoot is probably the reason tbh, I've had no issues with scanning but I also don't have ShipLoot in my pack
Nah, same issue with v1.0.0 ShipLoot
ShipLootPlus works fine, but has problems with micro stuttering when picking up or dropping items
oh my fucking god that makes so much sense to what happened to me recently
why does async and shiploot conflict to the point where you stutter at like 3 fps?
ShipLoot is barely supported, and even the dev said it's code is kind of messy and hacked together lol
"how many people were still using this one poorly documented mod-"
buddy- ye made an essential
I guess technically speaking I can rid it due to GI
since the monitor could be configured to show ship loot
but currently none of my monitors show in-ship loot... :c
Sellmyscrap can tell me how much there is.... .... bleh
that 3 fps stutter-fest was god awful, and it happened without me even being in the ship.
sooo who would have guessed Getting stacktraces is painfully slow
so the culprit is my attempt at Frankenstein stackTraces
#1217111718224728165 message
i'll push v1.5.0 soon with a Config option ( off by default ) for them
please do check v1.5.0 once it reaches r2 ๐
whats new in 1.5.0?
sqlite log output and a fix for a degradation in performance i introduced in v1.4.0
either use v1.5.0 or v 1.3.0
wait whats the issue? stack traces are slow, but since you're doing it in a separate thread, why's that causing the ui thread to freeze? ๐ฎ
i need to grab the stack trace before deferring otherwise i just get the stack of the new thread and not the one of who called the log ๐
oh true....
wait, was something causing you to create enough stack traces to freeze the game? that seems like that mod's problem tbh
seems odd if it worsens with AsyncLoggers as well
no i was creating a stacktrace for each generated log
wouldn't it be retrieving the same stack traces without async?
oh 
that'll do it for sure lol
as before writing it i have no way of knowing if it will generate a stacktrace or not, so i was just collecting them always and then patching together with unity ones if needed
i did not think reading the system stack was that heavy ๐ค
in java is a couple of msns at most
I think the main cost is looking up the instruction pointers
and trying to translate it with debug symbols if that's available
not that I know lol
a couple of ms is a lot of time in a game tbh
if it was a couple microseconds then that would be less of an issue
sry ns
ah
wrong unit
ms is def a lot of time XD
oh well, for debug purposes i left the code in there but behind a Deafult false config option
it did look like exceptions had the correct stack trace already, albeit with the extra thread's stack trace, were you trying to fix a different case?
the original ones have the stack of where the Debug.LogException was called, with async loggers that is lost
and replaced with AsyncLogger functions ( that normally make people give the blame to this mod for any exception ๐ )
so i was trying to patch back together the original stack trace, by stripping the unity one from the AsyncLogger methods and append the stack of before deferring
in this screenshot, would the stack traces be printed from a Debug.LogException() call?https://cdn.discordapp.com/attachments/1217111718224728165/1221153925076353074/image.png?ex=66118b37&is=65ff1637&hm=431d1382a2ba500964beaa7f3fc192818133f37ac6833af2967e6e32d583a29e&
yes
this is an example
oh, I guess that original stack trace is caught on the native side and rethrown at the source of the network message?
the stacktrace is generated on the native side yeah, it does not matter where the exception generated
hmm, it looks like Exception caches the stack trace, I wonder what happens if you just retrieve it in your LogException() override
I would've expected the rethrow to be at the original call site on the main thread in that case
but then again, I'm not sure why it wouldn't even without causing it to warm the cache
actually, I'm not so sure about my theory
but either way, I would've expected Exception to store the stack trace where it's thrown, it's bizarre that it generates it on the other thread instead
oof, looks like it would probably require reflection to solidify the stack trace on the main thread :(
I'll really have to take a deeper look at all this later, I'm beginning to think it's even more necessary to intercept these things sooner
oh wait a minute, this might come in handy https://learn.microsoft.com/en-us/dotnet/api/system.runtime.exceptionservices.exceptiondispatchinfo?view=net-8.0
or perhaps even a simple
void LogException(Exception exception)
{
try {
throw exception;
} catch (Exception e) {
[dispatch the exception to the other thread]
}
}
I think that may cause it to store the stack trace, if I understand things correctly
I was wondering why there's a random LogOutput.sqlite file now
are you noticing anything else? any stutters or problems?
i do not tink rethrowing it is the solution sadly
maybe there is a way to make it cache the stacktrace preventively
testing rn with this ๐ค
nope ๐
Works great now, thanks
Man is struggling in mod dev hell rn
Now there are problems with ShipLootPLUS, save files take much longer to load lol
@past cairn
๐
What did you do?
Lmfao
i can't even reproduce it... it happens randomly reeee
Btw while I have you here what did you recommend setting the timer to to avoid the voice stuck in wall issue?
not the timeout but the delay ( which is the time my mod waits between a completed connection and the start of the next one )
it's set to 5 seconds right now right? Maybe I should set it to 10?
never really tested which value works best... it's a matter of balancing how much your friends are will tollerate to wait before joining ๐
no it's 500ms = 0.5s
Ahhhh
I'll try changing it to 0.8 then
Since it's rare for people in my group to both join that quick
XD
yes try increasing it at steps and eventually you'll find a value that works
i mean this are my timestamps ๐
15:55:18.6798897 -
15:55:15.5597567 =
00:00:03.1201330
20k on ship
??
the queue
i see so many times people joining at the same time that funky stuff happens
hopefully MC update will fix those issues
this numbers are fantastic. i'm so glad people are liking my mod
17k on ship, takes ~1min to load for me
12k ๐
Your mod is awesome, I hope you hit a mil!
@past cairn so why was the sqlite stuff added btw?
for mod devs to be able to sort the logs in the order they actually generate
ah
so if there is a bug devs can request the sqlite instead of the .log and be able to see the full non filtered logs in the exect order
Did you find out why your mod dislikes the ShipLoot mods btw?
i mean the first one was the stacktraces, the second one i was not able to reproduce it ๐
i mean i was loading a lobby with around 20k in 3s
Idk if this mod make this error, but maybe anyone know how to fix that spam?
[19:42:34.1972852] [Error : Unity Log] ArgumentException: An item with the same key has already been added. Key: 11
Stack trace:
System.Collections.Generic.Dictionary2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <787acc3c9a4c471ba7d971300105af24>:IL_00DD) System.Collections.Generic.Dictionary2[TKey,TValue].Add (TKey key, TValue value) (at <787acc3c9a4c471ba7d971300105af24>:IL_0000)
Unity.Netcode.NetworkConnectionManager.AddClient (System.UInt64 clientId) (at <895801699cfc4b4ab52267f31e2a4998>:IL_0026)
(wrapper dynamic-method) Unity.Netcode.NetworkConnectionManager.DMD<Unity.Netcode.NetworkConnectionManager::HandleConnectionApproval>(Unity.Netcode.NetworkConnectionManager,ulong,Unity.Netcode.NetworkManager/ConnectionApprovalResponse)
Unity.Netcode.NetworkConnectionManager.ProcessPendingApprovals () (at <895801699cfc4b4ab52267f31e2a4998>:IL_0031)
--- End of stack trace from previous location where exception was thrown ---
AsyncLoggers.Wrappers.Unity.AsyncLoggerWrapper+<>c__DisplayClass4_0.<LogException>b__0 () (at <089cb954a275484eb6e0a994d7ad195f>:IL_0000)
UnityEngine.Logger:LogException(Exception, Object)
@rancid parcel here they come again ๐๐ญ
Sorry is my problem is stupid...
AsyncLoggers will show at the root of all stackTraces. this does not mean they are caused by this mod. typically the cause of the error will show up in the first few lines of the trace. please try and see if another mod is the cause first.. if you still belive it's caused by this mod tryt removing it and see if it still happens
damn, what all did you try?
both the ExceptionDispatchInfo and the rethrown exception
ah, that's frustrating
I gotta figure out how the inner exception's stack trace stays
For the sqlite database, can you pull in the mods that the user has installed into another table?
uhh sure that should be possible
Idk, was just a thought. That way debugging for devs might be easier with just the one file.
i mean tecnically the logs already have the modlist in them but a nicely ordered table definetly is a plus
That's true!
i was planing on adding an API to allow other mods to add arbitrary data ( intended for debug purposes only ) in the db alongside a generic event system
@past cairn can confirm the sqlite file being written makes performance worse
It wasn't Async Loggers, was another mod bugging out
Experimental release of v1.6.0
i'm interested in feedback mostly from other developers ๐ but also stability check by users
i will add more documentation in the future, this is just to gather some feedback ๐ฌ
code is in the Experimental branch on github
Is it intended to already be Deprecated?
yes, i 100% dont want any random downloading it thinking it's the official one and complain it is breaking stuff ๐
๐
adding a bit of documentation:
this release adds a softDependable API to allow mods to write two kinds of extra information:
eventsusing theWriteEvent(string source, string tag, string data, DateTime? timestamp = null):
indeded to be used to log macro events that will help you search the log sea by using the event timestamp as a referencemodDatausing theWriteData(string source, string tag, string data, DateTime? timestamp = null):
intended to be used to log any extra data that you deem too spammy to be put in debug logs but that will help debugging ( should be put behind a config as this will likely increase the file size )
both calls have the TimeStamp field as optional, if null it will generate a new timestamp once called otherwise will use the one provided ( all timestamps use the UTCNow format)
events should be rarer than the Info lines, eg: LobbyControl will use them to log when a lobby load or save is requested
there is also an example ProxyFile that i mentioned in the README but probably should also link it here
as i havent got any feeback. i decided to go though anyways and release the update to the main branch anyways
yeah, sorry, had some other stuff going on so I didn't get a chance to review the API
tbh I'm not sure if I'd have a use for it, but maybe
i'd like to see the events one used, as it will help a lot searching through the logs
but then as i did for troubleshooting the problem in Matty's Fixes having the logs in a db allows you to run super specific queries and filter out really well the logs ๐ค
yeah, I can see it being useful in niche situations at least
generally I don't have trouble finding things in the logs unless they've been removed with neuterer
i will definitely use the Data one to dump a bunch of super spammy stuff that i for sure dont want to see in the logs
timestamp ranges in really large log files will be useful certainly
yeah the bigger the modpack the larger the log files will be
so having timestamps and easy navigability is really usefull
Will be crashes fixed when quiting the game?
Exception while logging: System.Threading.ThreadAbortException: Thread was being aborted.
at AsyncLoggers.Wrappers.ThreadWrapper.LogWorker () [0x00074] in <089cb954a275484eb6e0a994d7ad195f>:IL_0074
Exception while logging: System.Threading.ThreadAbortException: Thread was being aborted.
at AsyncLoggers.Wrappers.ThreadWrapper.LogWorker () [0x00074] in <089cb954a275484eb6e0a994d7ad195f>:IL_0074
Exception while logging: System.Threading.ThreadAbortException: Thread was being aborted.
at AsyncLoggers.Wrappers.ThreadWrapper.LogWorker () [0x00074] in <089cb954a275484eb6e0a994d7ad195f>:IL_0074
Exception while logging: System.Threading.ThreadAbortException: Thread was being aborted.
at AsyncLoggers.Wrappers.ThreadWrapper.LogWorker () [0x000b5] in <089cb954a275484eb6e0a994d7ad195f>:IL_00B5
Exception while logging: System.Threading.ThreadAbortException: Thread was being aborted.
at AsyncLoggers.Wrappers.ThreadWrapper.LogWorker () [0x000b5] in <089cb954a275484eb6e0a994d7ad195f>:IL_00B5
Exception while logging: System.Threading.ThreadAbortException: Thread was being aborted.
at AsyncLoggers.Wrappers.ThreadWrapper.LogWorker () [0x000b5] in <089cb954a275484eb6e0a994d7ad195f>:IL_00B5
Crash!!!
...
(wrapper managed-to-native) Unity.Jobs.JobHandle:ScheduleBatchedJobsAndIsCompleted (Unity.Jobs.JobHandle&)
Unity.Jobs.JobHandle:get_IsCompleted ()
AsyncLoggers.Wrappers.JobWrapper:Schedule (AsyncLoggers.Wrappers.IWrapper/LogCallback)
AsyncLoggers.Wrappers.Unity.AsyncLoggerWrapper:Log (UnityEngine.LogType,object)
UnityEngine.Debug:LogWarning (object)
UnityEngine.ComputeBuffer:Dispose (bool)
UnityEngine.ComputeBuffer:Finalize ()
(wrapper runtime-invoke) object:runtime_invoke_virtual_void__this__ (object,intptr,intptr,intptr)
uh they should not be happening... i need to investigate this
are you on a different os?
linux / windows x32?
windows 10 pro
mmm are you searching where you normally find the LogOutput.log?
yeah
that's really weird can you send a picture of the folder with the LogOutput.log file?
wrong location
that's not the LogOutput.log folder
you'll find it in the profile folder under /BepInEx
yeah i'm just using it for my pack for now
i'll remove it once i get my pack finished
uh? does it.. it shouldn't as it is still running in a separate thread ๐ค
I found my game felt more stuttery with it on
also then what's the difference between the logoutput and player.log?
player.log comes from unity and will have some extra stuff/crash logs from unity
the LogOutput.log comes from bepinex and has all the logs from mods and from unity
for me it looks like there's more stuff in logoutput tho
also unity logs are marked as [Warning: Unity Log] on logoutput but not in playerlog
yeah bepinex listens to unity but not the opposite ๐
unless you toggle a setting in the config ecc...
generically it's better to use LogOutput.log unless you sre diagnosing hard crashes
i guess once i get back from easter vacation i'll have to check ๐ค
Yeah it could just be coincidence and another mod doing it tbh, cus it's still stuttery with it disabled too just feels a bit less so lmfao
placebo ๐คฆ
Would you be willing/able to make a column to ID each session (session being startup and shutdown of the game in a column), and then a config to only keep so many sessions in storage before deleting them? Like I normally only want to keep the logs of the last 2 sessions.
file rotation is based on the size of the file so the number of executions stored depends on how spammy your logs areand the size you defined in config
i have to say that the default 100mb is actually extremely oversized
of you only want to keep 1 ( + 1 rotation ) yoi can set the value to really small
i do log the application start in the Events tab, and i should also add a log for when a normal Quit is performed ( i can't log if the game crashes )
hey matty do u rmb approx how long the execution time for creating stack traces are on ur machine? im just curious approx how expensive it is
ehh between milliseconds and a second
it was extremely expensive @wicked coral
there is a proper c# way if you are the one that maintains the code and need to keep track of who called the method
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/caller-information
@past cairn just noticed you implemented your own ring buffer; do you know that Channel exists?
also, is there some interface I can implement so that your mod won't wrap my log sink?
no i didn't know about them, i originally used a queue then tried with a list but they were inherently slow, so i decided to go low level and write one myself taking inspiration from anlther one if found on github
will do some tests with channels once i get back ( ~ 2 days )
i do plan on adding a system to flag both sources and/or listeners as forcefully sync
but at the moment is not possible
based on the articles i found channels have similar performance to Queues. and improve only with tens of thousands of elements
so i will do my checks but our own implementation should still be faster
Thanks for the ROUNDS port ๐ซก
I actually meant the other way round - I have an async log listener but I have to act as though it's synchronous for BepInEx
It would be cool if there were some interface IAsyncLogListener with LogAsync on it
then you can if (logger is IAsyncLogListener asyncLogger) do something; otherwise, wrap it
the problem with using an interface is that it will require other mods to hard depend on AsyncLoggers
Hey what did you do to set the Apparatus to be ignored from rotating weird? I need to set it up for the Nucleus from Rosie's new interior
It used to show in the config but looks like you removed it

I don't think so
how do you implement an interface if you do not reference it?
and how do you reference it if the dll is missing?
I am verifying
You're right - I thought I had tested something but clearly not
i am thinking on either going the preloader route and use reflection to find specifically named methods or maybe using attributes if i can find a way to onky soft reference them
for an attribute pattern, your best bet is having a 'dummy' class
that will never be typeloaded by anything else
[YourRegistrationAttribute(typeof(SomeLogger))]
public static class AsyncLoggerRegistrationHolder;
you could use [assembly: ...] or [module: ...] attributes, but those cause Assembly.GetCustomAttribute<T>() to fail, and Netcode doesn't recover from that
i.e. lethal company breaks
Alternatively, I think it is possible to do some stuff with the AppDomain type resolution events
wtf god damn that's expensive, wasn't expecting it to take more than a millisecond
neither was i but then i was proven wrong ๐
NullReferenceException: Object reference not set to an instance of an object
at AsyncLoggers.DBAPI.SqliteLoggerImpl.Terminate (System.Boolean immediate) [0x00006] in <4a3c2cab9eee43eeb9fb32f30126a704>:0
at AsyncLoggers.AsyncLoggerPreloader.OnApplicationQuit () [0x00093] in <4a3c2cab9eee43eeb9fb32f30126a704>:0
at (wrapper delegate-invoke) <Module>.invoke_void()
at UnityEngine.Application.Internal_ApplicationQuit () [0x00022] in <e27997765c1848b09d8073e5d642717a>:0
NRE because sqlite is disabled?
yeah seems so... not a big issue so i will fix it next release
Hey
I might be having an issue with Async Loggers
Ill return in 5 minutes to confirm
@past cairn I just successfully spoofed an interface using Reflection.Emit and AppDomain.AssemblyResolve. Since I use that functionality in one of my mods I may make a very small lib for it
i.e, avoided ReflectionTypeLoadException when dependency was unavailable, and the actual dependency interface declaration is used when the dependency is present
to implement soft dependencies on mod assemblies?
if so, you can avoid loading classes from missing assemblies by blocking inlining of functions, it shouldn't require any reflection
To implement soft dependencies for interface implementation specifically
Say you have a class Animal defined by a game.
A mod library 'Foo' provides an interface IShearable that can be added to animals to allow them to be sheared
A mod 'Bar' adds a new animal, class Goat : Animal to the game. The developer wants the goat to be shearable, but doesn't want to hard depend on 'Foo'
They could use the method I've developed to allow them to implement the IShearable interface and simultaneously avoid the type load exception that would normally arise when 'Foo' is not installed
ahh, I see, that's cool
Getting the following errors when loading the game. I'm not sure if I have something set up wrong, or if there's an incompatibility. The error is only in the .log file and not the sqlite database. I will attach both logs and my config. These errors show up on almost every start up. Game seems to run fine otherwise, just thought I'd share in case there's an issue.
[Error : BepInEx] Failed to run Finalizer of AsyncLoggers.AsyncLoggerPreloader: System.IO.IOException: Cannot create a file when that file already exists at System.IO.FileSystem.MoveFile (System.String sourceFullPath, System.String destFullPath) [0x00013] in <787acc3c9a4c471ba7d971300105af24>:0 at System.IO.File.Move (System.String sourceFileName, System.String destFileName) [0x0007e] in <787acc3c9a4c471ba7d971300105af24>:0 at AsyncLoggers.DBAPI.SqliteLoggerImpl.Init (System.String outputFile) [0x00088] in <4a3c2cab9eee43eeb9fb32f30126a704>:0 at AsyncLoggers.AsyncLoggerPreloader.Finish () [0x0000f] in <4a3c2cab9eee43eeb9fb32f30126a704>:0 at BepInEx.Preloader.Patching.AssemblyPatcher.FinalizePatching () [0x0001e] in <fc9d7fbc6dcb44cf87be11d8d92ae161>:0
AND
[Error :Matty's Fixes] Exception while initializing: System.NullReferenceException: Object reference not set to an instance of an object at AsyncLoggers.DBAPI.SqliteLoggerImpl.WriteEvent (System.String source, System.String tag, System.String data, System.Nullable1[T] timestamp) [0x0004f] in <4a3c2cab9eee43eeb9fb32f30126a704>:IL_004F
at AsyncLoggers.DBAPI.SqliteLogger.WriteEvent (System.String source, System.String tag, System.String data, System.Nullable1[T] timestamp) [0x00000] in <4a3c2cab9eee43eeb9fb32f30126a704>:IL_0000 at MattyFixes.Dependency.AsyncLoggerProxy.WriteEvent (System.String source, System.String tag, System.String data, System.Nullable1[T] timestamp) [0x00000] in <0546a62864534675ab1f246fbe6d32dd>:IL_0000 at MattyFixes.MattyFixes.Awake () [0x000ce] in <0546a62864534675ab1f246fbe6d32dd>:IL_00CE
seems i made a mistake and AsyncLogger fails when there are two .sqlite files. just delete the older one. i will push a fix in the next few days
@tepid nova
Copy that! Thank you.
Does this work with v50?
Yes
can someone dumb this mod down for me
Game basically keeps a diary of what it's doing (aka logging) ๐
Currently both logger and game uses the same brain cell.. ๐ง
A single brain cell can only do so much juggling between the two before it gets messy (in the form of stutters) ๐ตโ๐ซ
Async logger makes it so that u can use more than one brain cell. u use two. TWO! one for logging and one for game. ๐คฏ
Less messy. Less stutter. Game run good. Run good mean happy gamer. 
i hope this is an apt explanation. now go download async logger. 
honestly i swear this needs to get pinned lmfao
@kind steeple Async Loggers Experimental
i've pushed an experimental release and the main class AsyncLoggers has a public method to register a ILogListener as ignored
AsyncLoggers.RegisterIgnoredILogListener(ILogListener toIgnore)
tell me if you can work with this ๐ค
Did you see my message r.e. interface mocking?
yeah i saw that but i want to experiment a bit more with it before using
BepInEx
yeah was about to say it. as the mod is fully a preloader
it will not show up in the BepInEx modlist
won't be able to give it a go just yet but will do
at runtime
yes, regardless, the convention applies (just minus the dependency attribute)
you need to use something like the integration i published for the DBAPI
yeah method impl but the issue is the Enable
You're saying I won't be able to query the chainloader to see if your mod is present
it will walways return false
Aye
so what i do is wrap a call to a MethodImpl call in a try catch and ignore it if it is a MissingDLL/Class/Method exception
The preloader must call an assembly, right? So I could query the AppDomain for a particular assembly name?
not super elegant but does the job
Yep, works too

like this
but you need to use a different call as this will return false also if the DBLogger is disabled ๐

@summer flare
@rancid parcel do you have any idea about this?
https://github.com/mattymatty97/LTC_AsyncLoggers/issues/6
user reported async loggers deadlocks after Chaniloader end on a 2 core CPU
i'm not even sure how he is able to boot LC with 2 cores tbh ๐
you're using the system library queue that DiFFoZ suggested now right?
if so, not sure what could cause that, but I wonder if you could get a profile code and try to reproduce by parking some of your cores
uh nope still our implementation
oh ok
casue the system library is slower
oh is it? the specific one that they suggested you mean?
has the same perofrmance as a normal Queue unles you're in the milion entires
then I would suggest trying to get a profile code and park cores to see if it's reproducible
it makes sense given how configurable it is
so many branches
but yeah, if you're able to repro in a debug build that would be really useful so you could find where each thread is waiting
without that it'll kinda just be shots in the dark
i mean i tried to run it on my Cenntrino Duo old pc... but let alone Async not even vanilla LC booted ๐
hmm, well I think the main ingredient would be the number of simultaneous threads
I suppose you could also set affinity in whatever you launch the game from, the game will inherit that on launch
hopefully that would save you parking cores
I'm assuming the game didn't boot on such an old PC just because of CPU features
I wonder if this person's dual core is hyperthreaded though
hmm
maybe it's something with the mods then 
it could be a specific timing in the log messages or something
other than that I'm not sure
would be useful to also know if it happens 100% for them
this booted in 1min and 45 sec ๐
lol oof
i mean this game ( and basically any other game exept mc ) are not really meant to work in a single core single thread scenario
yeah it makes sense
makes me wonder what it's threading though, Unity itself doesn't really encourage multithreading
but still does it behind the scenes with his Jobs
from the attached screenshot they are even using mirage which i believe will also suffer a lot from having limited cores ๐ค
am i wrong @wicked coral?
@rancid parcel got a code for the case but on my machine all boots fine with Affinity to 4/2/1 threads ๐ค
i have no idea of what's happening on their side ๐
mirage does most of its processing not on the main thread so limited cores does sound like it could be an issue
but idk 2 cores causes it to deadlock? thats interesting
i haven't been able to reprodce the problem even when limiting LC to a single core and single thread ๐
also just to clarify was not saying it is mirage fault, just that it might too suffer from the limited cpu
still boot times with 1 thread are sooo bad ๐
yeah i knew what u meant dw
honestly yeah even limited to 1 thread doesnt sound like it should suddenly deadlock
just makes it wait one after another
so everything becomes really slow
2 logical cores is interesting in today's age lmao
yeah.. i'm surprised the game even boots
lmfao it sounds rough for sure
i mean i tried to run it on my Cenntrino Duo old pc... but let alone Async not even vanilla LC booted
true old pcs arent gonna have a good time modded or not
damn, then I'm kinda out of ideas, but maybe it'll happen to fix itself if we switch out the queue implementation
i mean. one report is not enough for me to do a full rewrite XD. if you're close to the non locking version sure but otherwise i do not think we need to work extra on it
that's what I meant, yeah
I haven't really been testing that implementation in my profiles though since I've been focused on CullFactory when I do LC stuff
this is ok?
that is not ok, but is not caused by AsyncLoggers
if you're in doubt try and remove the mod and see if it still happens
99% of the time you'll still have the same errors
I am using AdditionalNetworking Experimental and i think that makes bees from beehive invisible
this is the error i can see
and this
i will check
now i got something relevant to additionalnetworking
you're throwing out items so fast that the mod is not able to keep up ๐
i think i got stuck in a loop
i think more than just additionalnetworking is the cause of the error
maybe throw everything and modelreplacement, or even enhanced icons
back again with some errors for additional networking
O.o
i found it, when i enabled more company. get like that
without morecompany normal fine no Error AsyncLoggers
this hsould have been fixed btw
it's even more weird then as more company has not been updated in months
yap that problem morecompany.
Morecompany 1.8.x Problem
old version like 1.7.6 work fine the AsyncLoggers
it's more likely to be induced by morecompany - maybe a third mod , all 3 transpiling the same method?
still there
now it's the on destroy ๐๐
@past cairn assuming this and Lobby Control are v50 compat, how about your other mods?
ok
just a tough i'll put a bit of my time into when i get back from vacation:
use a separate process to write to the DB to be able to keep all logs even in case of hard crashes
and use a memory mapped file
for the inter-process comunications
I'm not sure it's worth doing that, when Unity CTDs the logs aren't likely to contain anything useful immediately before the crash
unless you mean that the database gets completely corrupted when that happens?
Unity writes its own log to temp alongside a crash dump though
that'd be pretty odd if that were the case
no, no corruption but in case of crash all not yet written logs are lost
right
are there cases where those lost logs are needed? every crash I've seen has been the same one so far and it's never put anything in the logs that would be helpful
it was always a stack trace going from jit code for the SRP to shadow culling where normally no scripts are running
I would be really surprised if the game ever crashed in managed code
normally I'd support a fun project like that but doing stuff out of process sounds like it's getting into the territory of unnecessary complexity that will potentially cause some annoying issues
unity actually has a function to forcefully crash it๐๐
but yeah i agree there is no real need for it
i'd actually love to be able to put a handler to handle crashes but
1 i can only handle uncaught exceptions
and 2 even if i was able to catch a crash how would i even extract usefull information from the state of the process ๐
oh I forgot to reply to this but yeah, the crash dumps should contain everything we need for that but obviously without the Unity source there's not much use even in those
we can only extract the stack trace and search for it but most people probably won't even post questions with those since they don't know how to get them
the usual moon crash that's been going around I think is probably fixed in more recent versions but we're stuck with what Zeekers uses
[Error :AsyncLoggers] Exception while initializing the database! SQLite.SQLiteException: database disk image is malformed
at SQLite.SQLite3.Prepare2 (System.IntPtr db, System.String query) [0x0002a] in ./src/Sqlite/SQLite.cs:4605
at SQLite.SQLiteCommand.Prepare () [0x00000] in ./src/Sqlite/SQLite.cs:3238
at SQLite.SQLiteCommand+<ExecuteDeferredQuery>d__12`1[T].MoveNext () [0x00060] in ./src/Sqlite/SQLite.cs:3099
at System.Collections.Generic.List`1[T].AddEnumerable (System.Collections.Generic.IEnumerable`1[T] enumerable) [0x00059] in <787acc3c9a4c471ba7d971300105af24>:0
at System.Collections.Generic.List`1[T]..ctor (System.Collections.Generic.IEnumerable`1[T] collection) [0x00062] in <787acc3c9a4c471ba7d971300105af24>:0
at System.Linq.Enumerable.ToList[TSource] (System.Collections.Generic.IEnumerable`1[T] source) [0x00018] in <dab7f68612224ba3ae40f651d44f9d4c>:0
at SQLite.SQLiteCommand.ExecuteQuery[T] () [0x00000] in ./src/Sqlite/SQLite.cs:3070
at SQLite.SQLiteConnection.Query[T] (System.String query, System.Object[] args) [0x00009] in ./src/Sqlite/SQLite.cs:1105
at SQLite.SQLiteConnection.GetTableInfo (System.String tableName) [0x00011] in ./src/Sqlite/SQLite.cs:921
at SQLite.SQLiteConnection.CreateTable (System.Type ty, SQLite.CreateFlags createFlags) [0x0002a] in ./src/Sqlite/SQLite.cs:656
at SQLite.SQLiteConnection.CreateTable[T] (SQLite.CreateFlags createFlags) [0x00000] in ./src/Sqlite/SQLite.cs:631
at AsyncLoggers.DBAPI.SqliteLoggerImpl.Init (System.String outputFile) [0x000e1] in ./src/DBAPI/SqliteLoggerImpl.cs:73
Getting that error on the launch (even before the game itself starts), didn't notice anything wrong while playing, but thought it would be appropriate to send it here anyway
the .sqlite file got corrupted, either the game crashed or something went wrong while closing it previously
try amd delete the file and see if it recovers
otherwise you might have to disable DBlogging in config
thej01-FearOverhauled icon
FearOverhauled (I have no idea why this was sent at all lmao)
โ
ok its been a hot minute since i opened the LogOutput.sqlite in SQLite browser
but i canโt seem to open it :[
any clue why i canโt open it? iโm trying to find specific log @past cairn
not really, the browser program should tell you what the error is if there is any ๐ค
I think Async threw these errors and I don't know what they are related to
Nope, but I'm using BepInEx 5.4.23.2
i mean do you have it as a dependecy of another mod?
or you have only Bepinex and AsyncLoggers in the pack?
I can send you the profile code if that's gonna be easier to diagnose
But my list is pretty short since I'm playing on basically vanilla+ with a bunch of fixes and QoL for solo playthrough
019026d6-bee8-329d-e1f2-41118eb40c17
it might but. i know we had previous issues with it (https://thunderstore.io/c/lethal-company/p/www_Day_Dream/CessilCellsCeaChells/) as that mod seems to be breaking unity somehow
I don't have that mod
I'm gonna see if that error happens again if I relaunch the game
Seems to be a random error since this time, it didn't throw the error
Still weird
i do need to rework that part of the code eventually, but the error is something should never happen in C#
really weird i agree
a C# internal collection is finding the wrong type of object in it somehow
And not consistently at that. This error occurred at the launching phase of the game.
We need that from the OLDER .NET versiosn, this is when it's a no-op in .NET > 4 ^
this rethrows the eception tho ๐ค , the unity call is just feeding it to a lower level c function
ExceptionDispatchInfo exists in .NET > 4 for example, but in Unity we're .NET Framework 2.1 ofc.
i probably need to do a funky
try{
rethrow
}catch(){
orig()
}````
https://jainnitin2411.wordpress.com/2016/12/19/preserve-stacktrace-in-c-without-reflection-exceptiondispatchinfo-class/ is how people do exactly what AsyncLoggers does, but in .Net 4.x >
Shows taking exceptions from one thread and displaying them on another, with the original stack trace preserved
Exactly, looks like it might be something silly like this.
i tried the ExceptionDispatchInfo too.. it did not work
seems that the c part of unity appends the caller stack to the exception stack
and you've already tried all the innerException stuff too yeah? https://www.codeproject.com/Articles/5162327/I-Take-Exception
The other option is completely overwrriting Unity's loggers:
public interface ILogHandler
{
void LogFormat(LogType logType, Object context, string format, params object[] args);
void LogException(Exception exception, Object context);
}
var field = typeof(UnityEngine.Debug)
.GetField("s_Logger", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, your_debug_logger);
(as Unity passes the stack trace in as a string)
other formats like: ```cs
public static void SetupExceptionHandling()
{
if (!isExceptionHandlingSetup)
{
isExceptionHandlingSetup = true;
Application.RegisterLogCallback(HandleException);
}
}
static void HandleException(string condition, string stackTrace, LogType type)
{
if (type == LogType.Exception)
{
// .. send to thread
}
}
Wonder if this is more a C# thing or a Unity thing, but just offering approaches I find.
Btw, the "wrap exception" using PreserveStackTrace is exactly what Unity Sentry does
try
{
}
catch (Exception e)
{
SentrySdk.CaptureException(e);
}
Async Loggers has the option to wrap the LogHandler too
but has the same issue when the call is to the LogException
public void LogFormat(LogType logType, Object context, string format, params object[] args)
{
_wrapper.Schedule(wrapCallback(() => _baseHandler.LogFormat(logType, context, format, args)));
}
public void LogException(Exception exception, Object context)
{
_wrapper.Schedule(wrapCallback(() => _baseHandler.LogException(exception, context)));
}
ugh Hub -> IHub -> ? -_- seems like a loop trying to trace that, either way, we had examples before.
You probably have to wrap them before scheduling them (?) -- does scheduling happen on the other thread?
sheduling happens on the mian thread.. well, the Schedule is our own implementation and all it does is put the delegate in the queue
it's not actually scheduling a thread
public void Schedule(IWrapper.LogCallback callback)
{
if (_shouldRun != DefaultCondition)
return;
_taskRingBuffer.Enqueue(callback);
_semaphore.Release();
}
the "InternalPreserveStackTrace" seems to not be working... it cannot find the method with that name in the Exception class ๐ค
internal static readonly FastInvokeHandler preserveStackTrace = MethodInvoker.GetHandler(AccessTools.Method(typeof(Exception),"InternalPreserveStackTrace"));
love to mix and match utilities ๐คฃ
Nope still the same result :/
we have the first Addon for AsyncLoggrs:
https://thunderstore.io/c/lethal-company/p/mattymatty/AsyncLoggers_Filter/
by default all is allowed so logs will follow whatever is in the BepInEx config
are u saying i can singlehandedly block all mods logs with this 
cuz theres some mod that just like to spam
if you want sure. each detected mod ( ILogSource ) will have two cofig options:
- a bool to straight out disable it
- an Enum to choose what levels to show ( exacly the same format of BepInEx config )
this targets entire mods, logneuterer is more precise and targets specific log messages
yea thats the thing with logneuter, theres just too many lines for me lol
its time saving if u can just target the mod itself
i mean it originally was desinged to target the basegame logs... i'm not sure why people started using it for modded logs too
umm,, cuz theres config for it ?
unless i was thinkin wrong on how it works
that has a fatal issue... LogNeuter canot see any of the logs from mods that load after it
or to be more precise cannot see them when it generates the file
ohhh ok noted
im turning these to false
but the log still showing them?
or im i getting this wrong again 
that's weird are they using a 3rd logger?
uh nope it's all working for me
tho i'm mad at them for having a separate logger with the modversion
ok it worked for diversity
so whats 3rd logger again?
and will u add block console logging next
you see 2 entries for ReservedItemCore
a 3rd logger would mean a 3rd entry
wdym?
setting things to false prevent it from being written in the log file, but not on the console when playing the game
that's counter intuitive, you always want the more verbose one to be on file
now that i think about it thats tru 
and you can do that with normal BepInEx config
my cpu become 100% when add this is or only me?
now is normal version 1.1.2. version 1.1.1 make cpu 100% e.e

i mean v1.1.2 def has a big improvement by using semaphores to avoid busy waiting but still
Hi!
I don't know why this happens, but if I install this mod in my modpack, it's 70% possible that there will be a crash when loading
I can confirm that the mod is in its latest version
if you can give me a stacktrace or dump to work with ๐ค
Sure!
This is my modpack
When your mod is not installed, 1 out of 10 times it crashes when loading.
When your mod is installed, 9 out of 10 times it crashes when loading.
@short tusk Tested your pack, the crash reason is because of sound api
UnityEngine.Networking.UnityWebRequest:SendWebRequest ()
[./API/AudioFormatProvider.cs:16] loaforcsSoundAPI.API.AudioFormatProvider:LoadFromUWR (string,UnityEngine.AudioType)
[./Providers/Formats/OggAudioFormat.cs:13] loaforcsSoundAPI.Providers.Formats.OggAudioFormat:LoadAudioClip (string)
[./SoundLoader.cs:30] loaforcsSoundAPI.SoundLoader:GetAudioClip (string,string,string,UnityEngine.AudioClip&)
[./Data/SoundReplacementCollection.cs:43] loaforcsSoundAPI.Data.SoundReplacementCollection:.ctor (loaforcsSoundAPI.Data.SoundReplaceGroup,Newtonsoft.Json.Linq.JObject)
[./Data/SoundReplaceGroup.cs:36] loaforcsSoundAPI.Data.SoundReplaceGroup:.ctor (loaforcsSoundAPI.Data.SoundPack,Newtonsoft.Json.Linq.JObject)
[./Data/SoundPack.cs:159] loaforcsSoundAPI.Data.SoundPack:ParseReplacer (string)
[./Data/SoundPack.cs:150] loaforcsSoundAPI.Data.SoundPack/<AsyncParseReplacer>d__18:MoveNext ()
Cysharp.Threading.Tasks.CompilerServices.AsyncUniTask`1<loaforcsSoundAPI.Data.SoundPack/<AsyncParseReplacer>d__18>:Run ()
Disable multithreading option in configuration
thanks @flat rune ๐
Do you consider this and/or the normal AsyncLoader a must have?
I like SoundAPI's multithreading, but if this significantly improves performance, I may make the switch
the Filter mod does not provide any performance boost , it's entirely for people that like "Clean" logs
AsyncLoggers base on the other hand helps a lot with performance
but the base mod should not have any issues with other mods
as far as i've heard SoundAPI multithreading is quite unstable
i've decided to do a full rewrite of AsyncLoggers to have some cleaner code and to include the Filter in an embedded way
for the joy of @raw shuttle i've yeeted my attempts at patching the unity log classes and v2 will focus entirely on the bepinex side
( finally stacktraces will make sense again )
yey
this rewrite also brings back the order constraint so it is ensured logs will be written i the order they are emitted
also made BepInEx->Unity default to not async
performance loses quite a bit but again it ensures unity logs are consistent
( there will still be a config toggle if you want max performance )
https://cdn.discordapp.com/attachments/1200901735129022575/1273300976203206726/image.png?ex=66be1d71&is=66bccbf1&hm=d477c257fb5f385ed499acd14886535351cb5afd379d269005eeec2dc5b0c2e6&
i heard you complain that stacktraces were a mess with AsyncLoggers ๐
a lil bit
so those three things enabled ensures max perfomance?
all 3 of them yes. but this is for v2.0 that is not yet released
currently v1.x works a bit differently and also attempts to rewrite unity own logging system.. with a minor performance gain and an great distruption of error readability ๐
v2 will probably be released in Experimental sometime in the next week
for v2 can it have those 3 enabled by default cuz i feel most people download this mod for the performance not for the unity logs
the default off is a request by the people that need to help users in #help-and-troubleshooting
and currently need to request reruns with AsyncLoggers disabled to be able to have meaningful logs ( well i still think they are quite readable as they are but i gladly comply with their request )
there is already a big gain by having console and bepinex file async ( console especially )
but from my earlier profiler ( rough estimate nothing too scientific yet )
with a total time for the injection point of ~43ms
~35 were spent writing to the unity logs ( not async )
and less then 6ms for the others combined ( tho that's just the cost of scheduling to be executed l, as from that point on another thread is in charge of the computation and it will not affect the game anymore )
if anybody is intrested here's 90% of the calls to Debug.Log or derivates from inside Assembly-Csharp ๐
this is going to be a pain.. and i put myself into it w/o anybody asking ๐ญ
are you trying to patch em all to use BepInEx loggers or something?
that's an option i want to add.. for now i implemented a syste similar to LogNeuterer just without regular expressions ๐
i had to basically code my own decompiler in Cecil but the result is great imo
this is my current iteration of the config file for it for example
BepInEx works!
Throthling works unless it's a really complex logCall :/
toughts on this config format?
reworked comments thanks to ChatGPT ๐
i just remembered something @raw shuttle:
would you prefer to have Unity Player.log in order or BepInEx LogOutput.log ( and any other BepInEx listner tbh )?
as a default.
with the new system BepInEx is always in order but to have Unity in order i need to handle it synchronously and that's a decent performance hit ๐ค
as mentioned before it's just a bool toggle but most people would prefer performance to be the default
Uh, the bepinex log is all I need
I don't think you'll need to change much. LogMuncher is going to guess what is important either way and now with the debug assistant we get more info in logs
yeah this is more about the order of the loglines in the file than atcual dirty stacktraces ecc
any BepInEx stuff is guaranteed to be in order independently if it's marked as sync or async, but unity own Player.log can be in order only if handled sync
Well unity own logs are going to be in order but BepInEx logs written to unity log file wont be in sync with unity ones
I rarely use the unity player log so that's probably fine
V2 is now out in Experimental
- remove DBAPI
- add some api to handle custom ILogListeners
- remove patches to unity loggers
- embed AsyncLoggers.Filter
- immediately defer logs with a global Dispatcher Thread
- add LogWrapping system to edit basegame Log calls
Warning config files have changed place and are now in a sub-Folder.
please properly check README and the usage comment for the Log Wrapping
tested this.
This is the log
can i get a profile code? also what did you change from default configs?
nothing
01917560-f7fa-946e-e63d-c2af91f98e48
this going to take a while to import ๐
I recommend Gale, < 3 minutes
yeah i'm using gale
ok i found one issue. apparently i set the default false to the wrong property ๐
current version has all the Enabled options in the LogFilter config file to false
so all logs are not printed ๐คญ
oh
will push a new version soon to fix that. i'm looking at the errors to see if they were cause by me too ๐ค
man it takes a lot of time to boot up your pack ๐คฃ
ok no all the exceptions are native from your pack. only issue was AsyncLoggers was hiding all logs from mods by default
i'll upload a fix immediately
Should be available on Gale soon. please delete AsyncLoggers configs and let them regenerate
@carmine crystal turns out #1263238359346843712 breaks badly if AsyncLoggers tries to edit any log call inside RoundManager.SyncScrapValuesClientRpc ๐ค
for now the workaround is to forcefully set this specific config values to Unity
<Method name="SyncScrapValuesClientRpc">
<!--Edit 'status' to customize log behavior-->
<LogCall status="Unity">Log(Format("clientRPC scrap values length: {0}",allScrapValue))</LogCall>
<LogCall status="Unity">LogError(Format("spawnedScrap amount exceeded allScrapValue!: {0}",spawnedScrap))</LogCall>
<LogCall status="Unity">LogError(Concat("Scrap networkobject object did not contain grabbable object!: ",#1.gameObject.name))</LogCall>
<LogCall status="Unity">LogError(Format("Failed to get networkobject reference for scrap. id: {0}",spawnedScrap[#3].NetworkObjectId))</LogCall>
</Method>
Simple fix is I could probably just disable logging from that class
don't really need it anymore LOL
that should theoritically fix it right?
it's not about your mod doing logs
it's about your Transplier? ( ILHook maybe )? crashing bad and in turn crashing the entire game
[21:47:20.3870395] [Error : Unity Log] ArgumentException: Label #15 is not marked in method `SyncScrapValuesClientRpc'
Stack trace:
System.Reflection.Emit.ILGenerator.label_fixup (System.Reflection.MethodBase mb) (at <787acc3c9a4c471ba7d971300105af24>:IL_0053)
System.Reflection.Emit.MethodBuilder.fixup () (at <787acc3c9a4c471ba7d971300105af24>:IL_006B)
System.Reflection.Emit.TypeBuilder.CreateTypeInfo () (at <787acc3c9a4c471ba7d971300105af24>:IL_0307)
System.Reflection.Emit.TypeBuilder.CreateType () (at <787acc3c9a4c471ba7d971300105af24>:IL_0000)
MonoMod.Utils.DMDEmitMethodBuilderGenerator._Generate (MonoMod.Utils.DynamicMethodDefinition dmd, System.Object context) (at <6733e342b5b549bba815373898724469>:IL_001B)
MonoMod.Utils.DMDGenerator`1[TSelf].Generate (MonoMod.Utils.DynamicMethodDefinition dmd, System.Object context) (at <6733e342b5b549bba815373898724469>:IL_0013)
BepInExMonoModDebug.DebugDMDGenerator._Generate (MonoMod.Utils.DynamicMethodDefinition dmd, System.Object context) (at ./DebugDMDGenerator.cs:31)
MonoMod.Utils.DMDGenerator`1[TSelf].MonoMod.Utils._IDMDGenerator.Generate (MonoMod.Utils.DynamicMethodDefinition dmd, System.Object context) (at <6733e342b5b549bba815373898724469>:IL_0000)
MonoMod.Utils.DynamicMethodDefinition.Generate (System.Object context) (at <6733e342b5b549bba815373898724469>:IL_00D4)
MonoMod.Utils.DynamicMethodDefinition.Generate () (at <6733e342b5b549bba815373898724469>:IL_0000)
(wrapper dynamic-method) MonoMod.RuntimeDetour.ILHook+Context.DMD<MonoMod.RuntimeDetour.ILHook+Context::Refresh>(MonoMod.RuntimeDetour.ILHook/Context)
(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition.Trampoline<MonoMod.RuntimeDetour.ILHook+Context::Refresh>?958856456(object)
HarmonyLib.Internal.RuntimeFixes.StackTraceFixes.OnILChainRefresh (System.Object self) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0000)
MonoMod.RuntimeDetour.ILHook.Apply () (at <4e2760c7517c4ea79c633d67e84b319f>:IL_0059)
HarmonyLib.Public.Patching.ManagedMethodPatcher.DetourTo (System.Reflection.MethodBase replacement) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0047)
Rethrow as HarmonyException: IL Compile Error (unknown location)
HarmonyLib.Public.Patching.ManagedMethodPatcher.DetourTo (System.Reflection.MethodBase replacement) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_005F)
HarmonyLib.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, HarmonyLib.PatchInfo patchInfo) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0033)
Rethrow as HarmonyException: IL Compile Error (unknown location)
HarmonyLib.PatchClassProcessor.ReportException (System.Exception exception, System.Reflection.MethodBase original) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0045)
HarmonyLib.PatchClassProcessor.Patch () (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0095)
HarmonyLib.Harmony.<PatchAll>b__11_0 (System.Type type) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0007)
HarmonyLib.CollectionExtensions.Do[T] (System.Collections.Generic.IEnumerable`1[T] sequence, System.Action`1[T] action) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0014)
HarmonyLib.Harmony.PatchAll (System.Reflection.Assembly assembly) (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_0006)
HarmonyLib.Harmony.PatchAll () (at <474744d65d8e460fa08cd5fd82b5d65f>:IL_001B)
SkinnedRendererPatch.SkinnedRendererPatch.Patch () (at ./SkinnedRendererPatch.cs:70)
SkinnedRendererPatch.SkinnedRendererPatch.Awake () (at ./SkinnedRendererPatch.cs:31)
UnityEngine.GameObject:AddComponent(Type)
BepInEx.Bootstrap.Chainloader:Start()
UnityEngine.Rendering.HighDefinition.HDRenderPipelineAsset:OnEnable()
Eeesh guessing I should remove this for now?
or do this ^
i see why ๐คฃ
yeah ๐ญ
just saw that too LOL
removing the IL code for the logs should fix it then
this means you are also incompatible with LogNeuterer btw
don't really need to transpile it but without that vanilla will throw false error messages I can't really do much about iirc
just nobody ever cared about patching thoose calls out
ohh you're wrapping the error calls in a if to skip them
yeah, its been a hot minute since I worked on that mod but iirc something with vanilla is hardcoded to look for a component and would throw error messages in scenarios where nothing was really wrong
those were there to stop the false error messages from appearing and freaking people out
i'm trying to think on how i could help you be compatible but while in the redirect cases it would be simple ( my wrapper methods all start with Log* too )
in the case i Suppress/delete the calls it's going to be problematic ๐ค
i see why it crashes so bad ๐คฃ .
you try to grab the three values insertionIndex exitIndex jumpIndex
but never check if you actually found valid values
disabling the transpiler completely seems like the best option honestly,
[23:19:13.7416660] [Error : Unity Log] Scrap networkobject object did not contain grabbable object!: EnginePart(Clone)
it gives these false errors but avoiding a transpiler might be the best option for compatability here
doesn't affect the stability of the mod either, works just as intended without it
nor do the errors effect actual gameplay
you could probably just do a HarmonyPriority HarmonyBefore to patch before AsyncLoggers, no?
I would assume that would mean both would patch successfully, if AsyncLoggers is checking for all calls to Debug.Log
AsyncLoggers is a preloader and uses mono.Cecil to modify the assembly before it even loads.. good luck patching before me๐
ah right, forgot about that
i might have to say it explicitly. but please give any feedback you feel needed on this Experimental version
and for who likes to mess around with stuff, please try the logWrapper settings ๐
@kind steeple i remember you wanted a way to request AsyncLoggers not handle a ILogListener.
i've kept the old method in there for retro-compatibilty but marked it as Obsolete would you mind looking at the new Entrypoints if anything has to be changed?
is what i actually wanted
like, I've implemented an async log listener but I have to execute it synchronously for bepinex
I want to be able to tell Async Loggers that my logger implements an async interface
so Async Loggers will call my logAsync or whatever, instead of wrapping my synchronous log function
(hypothetical function names)
i can add your requested interface. but as i said back then for you to implement it you would have to hard depend on my mod. ( which is not my issue tbh )
rn i just exposed 3 new methods for you to mark your listener with
wait maybe i've read it wrong before
you want an interface that adds a AsyncLogEvent(...)
as opposed to BepInEx native
void LogEvent(object sender, LogEventArgs eventArgs);
and have AsyncLoggers call that instead of wrapping the native BepInEx one?
yeah
something like that
uhhh
no not really
uhhhhhhhhhhhhhhhhhhhhhhhhh
maybe
I am unsure ๐
i mean i could but why would you? if you're writing a new LogListener just make a separate async one instead ๐ค
OK, I don't see why it needs to be AsyncLogEvent
and tell AsyncLoggers to not wrap it
Because that defeats the point of async loggers
My log listener runs asynchronously but I have to call it synchronously, which means I end up with some errors potentially being lost to the void
I want to skip the 'calling it synchronously' bit when Async Loggers is installed
the point of AsyncLoggers is to move logs away form the main thread.. if your listener already does that and wants to ask AsyncLoggers to not make it "even more async" that's perfectly in line with the Idea
wdym Calling it sync?
if your listener is async means it does not block the call to LogEven and immediately or almost gives the control back to the main thread
the main thread has to put the log events into a queue (which is an async function) for the worker thread to work through
the async function to 'add to queue' has to be called synchronously
which means what it actually does is 'fire off' the add to queue Task
without waiting for it to finish
that's not something your listener will ever see or feel tho
if your listener does that then it indeed is async? whst do you mean with it needing to be called "sync"?
why are you putting 'sync' in quotes, that's the terminology
i wouldn't put 'async' in quotes
any async call by definition will be requested from a sync one ๐
but that's not what i said
i said synchronously
i have to do something async, but pretend it's synchronous
because otherwise it will break bepinex
i.e. i have to start this async task and immediately tell the main thread to forget it asked it to start
I would much prefer being able to await the task
if you await an async taks youre just making it become sync tho ๐ค
yes, that's what I want in this case - the main thread should block until the queue accepts the log message
i'm sorry you're loosing me in technicalities ๐๐
๐
because I know the queue will generally accept the log event fast
Surely you have a similar thing for async loggers ?
to ensure log messages keep order?
i have implemented a cusom RingBuffer and enqueue Actions thst are then consumed by a single thread
i create a new thread and Buffer for each of the Listeners i need to wrap
the ordering is ensured by the fact that i have only one consumer for each buffer
i do not care how fast the consumers are i just care about moving the work away from the main thread
okay, i getchu
you're probably right that what we need is for me to be able to tell Async Loggers not to wrap my thing
since my thing doesn't block the main thread
so where can I see the new method of asking to be ignored?
same as before it's a public method on the main class
i've also added a brief description in the README
and:
For the Developers:
the main class AsyncLoggers.AsyncLoggers contains 4 methods to register your own LogListener into AsyncLoggers system:
- SyncListener (listeners will receive logs directly)
public static bool RegisterSyncListener(ILogListener listener)
public static bool UnRegisterSyncListener(ILogListener listener)
- UnfilteredListener (listeners will bypass the user defined filters and receive all logs)
public static bool RegisterUnfilteredListener(ILogListener listener)
public static bool UnRegisterUnfilteredListener(ILogListener listener)
- TimestampedListener (listeners will have the TimeStamp prepended to the LogEventArgs Data)
public static bool RegisterTimestampedListener(ILogListener listener)
public static bool UnRegisterTimestampedListener(ILogListener listener)
i might have to reword the first one better ๐ค
You're gonna hate me for this
But this would be way nicer:
[Flags]
public enum LogListenerFlags {
Default = 0
Synchronous = 1 << 0
Unfiltered = 1 << 1
Timestamped = 1 << 2
}
public static bool RegisterListener(ILogListener listener, LogListenerFlags flags)
->
RegisterListener(myLogListener, 0
| LogListenerFlags.Synchronous
| LogListenerFlags.Timestamped
)
and also more maintainable for you ๐
๐ค i'm not too sure if retrieving a FlagEnum from a dictionary and then do the mask check is faster/slower than just checking if the item is in a set...
definitely possible for me to implement. but it needs some testing
V2.0.3 is in Experimental
- implemented a system to always load the assemblies in dependency order in the LogWrapping step
for LethalCompany the entire list of patchable Assembiles that do not cause issues if modified is:
UnityEngine.PropertiesModule.dll,UnityEngine.AndroidJNIModule.dll,UnityEngine.SubsystemsModule.dll,UnityEngine.UnityWebRequestWWWModule.dll,UnityEngine.GameCenterModule.dll,AmazingAssets.TerrainToMesh.dll,Unity.VisualEffectGraph.Runtime.dll,Unity.Timeline.dll,Assembly-CSharp.dll,Unity.AI.Navigation.dll,UnityEngine.VideoModule.dll,Unity.Netcode.Components.dll,Facepunch Transport for Netcode for GameObjects.dll,Assembly-CSharp-firstpass.dll,UnityEngine.TerrainModule.dll,Unity.TextMeshPro.dll,UnityEngine.UI.dll,UnityEngine.UIElementsModule.dll,UnityEngine.IMGUIModule.dll,UnityEngine.TextCoreTextEngineModule.dll,UnityEngine.Physics2DModule.dll,UnityEngine.TextRenderingModule.dll,UnityEngine.AIModule.dll,Unity.Netcode.Runtime.dll,Unity.Networking.Transport.dll,Unity.Multiplayer.Tools.NetStats.dll,UnityEngine.AudioModule.dll,UnityEngine.AnimationModule.dll,Unity.ProBuilder.dll,UnityEngine.PhysicsModule.dll,Unity.Services.QoS.dll,Unity.Collections.dll,Unity.Burst.dll,UnityEngine.CoreModule.dll
PS: i tested it with this assemblies , it boots and i was able to join a new save.. i have not tested the full gameplay. so more pruning might be necessary to ensure the game runs without issues
How you implement it in the backend is inconsequential - whether you have 1 set per flag etc - but in terms of outward-facing API, you want to reduce that surface as much as possible so you have less to worry about r.e. breaking changes and your SemVer contract
and also, 1 method for consumers is nicer than 3 ๐
i always tought extensive API were better than single contact points.
but i've never really worked with APIs so this was just my guess
i'm not sure what you mean by extensive vs single contact
do you mean descriptively named (by extensive)?
single method to do everything vs many methods that each does something different
ah, I see
functions in general sould 'do one thing, do it well, do it tell'
API functions included
i've had to work with some web apis in my workplace and i always hated the ones that gave me a single url to do everything based on the input
and loved the ones where each action had a different page
but equally, don't have 10 functions that do the same thing, where you could have 1 function with an extra parameter
web APIs are kind of a different ball game, and I get where you're coming from
but i can see how it would be cleaner in this instance to have a single method and use a flag system
โค๏ธ
yeah in the implementation you can still do
if (hasOneFlag) addToOneSet()
if (hasTwoFlag) addToTwoSet()
if that's your preference
yeah that's what I'm going to do
In terms of asymptotic complexity, there is no difference between getting from dictionary plus doing the has flag computation, and the set .contains
parse the flag immediately in the method and add stuff to the sets depending on it
in terms of actual time / instructions - there will be a difference - but I think it would probably be negligible
not really when you'll have to call it thousands of times per tick in some instances
every performance i can squeeze out of it matters
well this is before i enqueue it and offload it to a new thread
The time taken to hash the whatever it is for the dictionary/hashset lookup will far outweigh the binary AND and brnull
oh that's for sure
but i have to do the hashing in both cases while i need to check the flag only on the second
because i cannot attach the flsg directly to the object ( sadly C# does not allow monkey-patching ) :/
so i would still need to store a dictionary of flags
but the and operation is indeed super cheap that is not even worth profiling ๐
that's what i'm getting at haha
if the hashing is fast enough x1000 per second, you don't need to worry about an AND and brnull x1000 per second as well
because the hashing is orders of magnitude slower
well that's the neat part. i'm not using hashes ๐ . as i'm fine with object identity beeing used as comparsion the default hash function is actually almost free ( or so i read in the documentation )
but still indipendetly by what i'm using internally i'll change to the flag system either on Monday or Tuesday depending on when i'll be back :D
oh yes it is - since it's just using memory addresses as the hashcode
@kind steeple how's this as an EntryPoint?
YEET logs in their own Thread! Contribute to mattymatty97/LTC_AsyncLoggers development by creating an account on GitHub.
ops i love the typo
TraceableLevelsMask ๐
for any log with a level matching that mask AsyncLogggers stops to get a stacktrace and stores it in the sqlite DB
it's there in case somebody needs it otherwise it's just defaults ๐
Speaking of traces, any of you smart people got any ideas about why dynamic methods disappear from the stacktrace and leave it broken and how I can figure out the actual calling method when an exception is supposed to originate from a harmony patched method?
I've seen people post UDA parsed logs that have harmony methods visible in them but when I test it locally I can never get a patched method in my stack trace but unity can and it spits out (wrapper dynamic) <final stack crame I'm missing here> each time
do the dynamic methods show up if you do StackTrace.ToString()? I suspect it might be because Unity is printing the stack trace from the native Mono API instead of .NET
It doesn't show up in the exception's stack trace, the env stacktrace a newly created stacktrace (which likely reads from the env) or anywhere else
I also tried patching every single debug.logexception method in unity all the way down to static private logexception_internal which is just an extern declaration and I only catch exceptions that are actually debug.log'd in client code. Unity has a first chance handler in UnityEngine.Core that calls Debug.Log but its never used as far as I can tell
I was willing to say that dynamic methods 100% always break the trace but then #1213797469192855553 message this person posted a log where a bug in the harmony patch rendering logic was showing "mscorlib" instead of the actual patch name so somehow they got an actual trace from harmony
looking at https://www.mono-project.com/docs/debug+profile/debug/, it does kinda seem like this must be a stack trace that's accessible from the Mono runtime
not sure if there's any way to access it in a managed context, but I suppose maybe there is some way
bleh
purely cosmetic question ๐
which version is better:
<LogCall obsolete="true" status="Default">LogError(Format("Baboon #{0}; Error, was not able to get network object from dropped item client rpc", this.thisEnemyIndex))</LogCall>
<LogCall status="Default">UnityEngine.Debug.LogError(System.String.Format("Baboon #{0}; Error, was not able to get network object from dropped item client rpc", this.thisEnemyIndex))</LogCall>
๐ญ
i took so long but now i can also handle Ternary (?) operators:
<LogCall status="Default">UnityEngine.Debug.LogError(System.String.Concat(selected, (selected ? selected.ToString() : null), "while already selecting an object."))</LogCall>
let me reword the question:
In the case of Static Methods is it better to:
- print only the Method name ( eg:
Format("formatting string", args)) - print only the Class name and Method name ( eg:
String.Format("formatting string", args)) - print the Full Class name and Method name ( eg:
System.String.Format("formatting string", args))
reminder that i have no way of differentiating builting types from custom ones so all of them will receive the same treatment
V2.1.0 is in Experimental
- remade the API by suggestion of @kind steeple
- rewrote the decompiler used for LogWrapping
PS:
existing LogWrapping config will need to be redone, old entries will not be deleted but marked as obsolete
@pulsar forum are you trying to start multiple instances?
yeah
Yeah
the LogLevels file get's generated on the first execution. and is populatede each time a new logSource writes ( or attempts to write ) a log
if you dont want debugs globally just disable them from bepinex config as this mod works on top of it
I want debug from one mod specifically
run the game once then use notepad or notepad++ to replace All with the list you want
i can probably add a Default setting at the top of the file tho
but i cannot easly handle the other fields ๐ค
Eh, this works well enough
it doesn't seem to hide these messages though
weird they shold be hidded ๐ค
soo i tried again and it works fine for me ๐ค
ik gale does not write it to config until you either click out of the config tab or click on a different setting ๐ค x2
It writes with every change
i've had instances with this flag type settings where i had to click another setting or more consistently go to the modlist and back to the config
this also happens with the string list ones, but that is just visual on Gale and it is actually written to disk
huh ok
I'm pretty sure that wasnt happening though
since wouldn't info messages also be there in that case?
depends if you went immediatly to Error.Fatal or if you had a step at Warning
if not, then i have no idea why it happend on your side ๐
FilterConfig.cs used in LogEventWrapper.cs
dont really have edgecases ๐ค
the filter is read based on the SectionName and is just put in a bitwise and with the loglevel of the event
AsyncLoggers V2
Now in Stable!
o0oOOoOOOOO
So, my game is not writing any logs to Disc whatsoever, as I disabled logs and stuff. Do I still need this mod?
yep because it should work on any BepInEx version from multiple games. so i cannot lock it to a specific game BepInEx package ( because TS has different packages for different games )
Should I keep "do not collect stack traces" disabled to ensure better performance
Should I keep LogWrapping enabled to ensure better performance?
log wrapping on it's own will not change the performance, it needs to be configured and even then it wont significantly improve them ( it is intended as an alternative to NoConsoleSpam kind of mods )
the default behaviour of AsyncLoggers is to halt and collect stacktraces for Error level logs, if your modpack likes to throw a lot of Errors, imo you have some bigger problems, but disabling the stacktrace collections will indeed improve performance
@past cairn Could you explain what the AsyncLoggersLogLevels config does? like, if I disabled a source to write logs, would that mean better performance?
if you have AsyncLoggers there is not going to be a performance gain from using the LogeLevels config. it's there for the people that like to have a clean logfile / like to keep the console window open and still be able to read it ๐
Good to know
where do i find this ?
If I disable showing the console for log output, would that improve performance? I assume not, but I felt like asking just in case it does.
@past cairn sending a followup. Just wanted to know if thereโs additional ways to into performance related to logs.
Does disabling showing the console for log output increase performance?
https://thunderstore.io/c/lethal-company/p/Mhz/DisableUnityLogs/
does this mod help?
Iโm pretty sure you can already do this in BepInEx
At this point, I want to know if thereโs anything I can do that stops logs altogether, leading to improved performance, even if itโs negligible
if you want maximum performance possible then disabling all logging options in BepInEx config will give you that. and at that point you do not need AsyncLoggers.
the improvement compared to having logging enabled with this mod will be minimal.
and any log related lag will still persist as Unity itself still creates and saves logs in the Zeekers save folder anyways
Thank you
small update to add a new community:
AsyncLoggers v2.1.4:
- added R.E.P.O listing
- stacktraces are now opt-in instead of opt-out
i have been getting this error for some reason
the database got corrupted... did you have hard crashes by chance?
yes
i already tried reinstalling as it would not launch with the mod enabled at all
in your profile folder ( where you have LogOutput.log ) find and delete LogOutput.sqlite and derivates
or just make a new profile
that fixed it
thanks
Async Loggers Experimental v2.2.0 ( 21.2.0 )
- rewrite internals for hopefully better performance, reliability and readability
- make BepInEx intercept UnityLogs from other threads (mainly from jobs)
- do not prune orphan entries in FilterConfig
finally had time to finish the rewrite from the Experimental branch ๐คฃ
make BepInEx intercept UnityLogs from other threads (mainly from jobs)
@rancid parcel if only we had this when we were testing PathfindingLib
it's a rewrite and its experimental use at your own risk
but please test it and give feedback ๐
What does intercept unity logs do?
BepInEx only shows unity Logs from the main thread
ooh nice
if a Worker thread sends logs they are only visible in Zeekers/Unity " Player.Log"
AsyncLoggers catches logs from other threads too now
definitely would have helped at the point where I was under the impression that it should have logged things lol
well once TS allows the package back on the platform
That sounds really helpful
I forget if there's something that even Player.log misses though
i got the pages delisted rn ๐
I know there were a few times when I was debugging stuff and it only showed in player.log
player.log currently shows also the normal Console.Out.Writes
When I first read it I got it mixed up, I thought it would differentiate vanilla and mod calls to unity log
Since some mods dont use MLS
sadly it's not that simple to differentiate them :/
fun fact about this rewrite:
i cannot patch BepInEx Chainloader.Start
i can do whatever i want to Chainloader.Initialize but if i touch Start in any way unity itself will stop working and start throwing MethodNotFound errors already inside Initialize ๐
it was so hard to debug and pinpoint ๐ญ
You can patch it, but you need to wait when Initialize is completed
You ended up also pushing the update to the live version though lol
i just tried out the experimental version rn
I tested it earlier and I can notice the performance increase
1: the first and second time starting the game caused the chainloader to run way slower than on stable, stable takes <1 min to load for me but this was taking 2-3 min. after those loads i switched to stable and back, and then it ran at the same speed as stable, which was really confusing
2: if there were any specific performance improvements during gameplay, they weren't noticable. it actually made my ship fps a little worse by 1-3 frames
3: it breaks loadingscreen, gets stuck on this message forever
Oh fun
I think the performance diff will mainly matter after playing for a while
the game generally slows down overtime as you play
i suppose
as far as making bepinex read the non-main thread logs, i didn't see which ones they would be cus i havent played for a bit
Yeah it does
they probably both hook into the same process
I kinda dislike LoadingScreen anyways
it sometimes bugs and gets stuck on the screen regardless
kinda annoys me
it happens so rarely that i dont mind
ehh there probably wont be any perceivable improvement in performance. all logs were already processed in a separate thread and that thread is what got optimized ๐
that's an approach i can definitely try. my current solution is to patch LogMessage and wait for the Chainloader completed message then unpatch LogMessage ๐
@lone stone Your issue with boot times being slow is probably edge game assist btw, I disabled Game Bar in my Windows 11 cus that kept slowing down boot times
Cus I can't repro that
I already debloated my win 11
It couldn't be that
That shit always reinstalls itself and runs in the background if you don't disable Game Bar with gpedit or smth I found
I ran Chris Titus' windows utility after it did updates
There is no way it would be gamedvr coming back
God I would never run a program like that
Too easy to uninstall important shit that might cause Windows to become bricked from an update
chris titus is not a one click debload utility tho.
it just shows in a nice ui what things people want to toggle the most
i definitely would not recommend one of those auto debloat batch files tho
but chris titus and/or O&O shutup10+ are quite good at showing you what can be toggled
Maybe if you dont click the stuff that it tells you not to click it wont brick your computer
But I know its not comprehensive
I did run o&o shutup10+ as well for disabling telemetry stuff
But i wanted to do this one as well since it had more useful stuff and I could understand it
Cus I have some pc knowledge but not enough for any of the more advanced debloating stuff
@flat rune later today i'll have to ask you for help on how to have a preloader download a file via https.
i can get http working but tls seems to be missing ๐
it's just not possible
and legacy mono tls provider doesn't support tls1.2/1.3
uh? have you not done it for FixPluginTypes thing?
it didn't work
hm, actually it did work, but it's just making patching in chainloader initialize
FPTS currently did just making an external c# console program to download pdb https://github.com/xiaoxiao921/FixPluginTypesSerialization/commit/b93d2bf9d853b7ccfee17dcd0e4db95a0067b5ed
there is also a pr that uses P/Invoke winhttp.dll https://github.com/xiaoxiao921/FixPluginTypesSerialization/pull/9
so you could try the P/Invoke instead
if you're really need that file before unityplayer is loaded
well i'm already using kernel32.dll LoadLibrary for loading the sqlite dll ๐
let's add a couple more red flags for TS checks and load winhttpd.dll too ๐คฃ
โ ๏ธ
uh so the experimental version of this mod, makes these BepInEx logs don't appear anymore:
[Info : BepInEx] Loading [(Mod name here) (version here)]
[Message: BepInEx] Chainloader startup complete
and that breaks the mod https://thunderstore.io/c/lethal-company/p/Bertogim/LoadingScreen which depends on that
anything you can do?
i once tried to read logs from other mods but i wasn't successful, so i depend in BepInEx logs
uh. weird . the BepInEx logs definitely are supposed to show up
i'll have to debug that this evening
@flat rune winhttp.dll works like a charm 
i'm sorry TS Moderators, AsyncLoggers will trigger so many of your flags from now on ๐
Should change the name to SusLoggers
lol
