#Async Loggers

1 messages ยท Page 2 of 1

rancid parcel
#

if it is maybe it'd be better to convert to seconds or something

past cairn
#

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

past cairn
#

@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

grizzled jacinth
#

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 ๐Ÿ˜…

rancid parcel
#

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

past cairn
#

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 )

rancid parcel
#

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?

past cairn
#

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

rancid parcel
#

gotcha, that does seem like a bit of a pain

past cairn
#

it is necessary to keep track of the right timestamp sadly

rancid parcel
#

maybe if I rework it the way I described that could be improved but we'll see if that actually functions

#

yeah

past cairn
#

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

fast torrent
#

@pure trail could we get a pin on this? ๐Ÿฅบ

rancid parcel
#

oh I just realized I was looking at the wrong branch

past cairn
#

lol

#

yeah i probably will switch this as the main branch now

rancid parcel
#

I had rebased onto master earlier and was wondering why it wasn't a preloader

pure trail
past cairn
past cairn
vestal fox
past cairn
#

#modding-general message

#

if i remember right this kind of error is caused by MoreCompany

vestal fox
#

so tis coincidence it's between 2 LGU console stuff? . ,.

past cairn
#

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

past cairn
#

so apparently the the logs that we're not catching simply pop up from nowhere ๐Ÿ˜… they trigger the logGeneratedEvent wihtout it originating from anywhere

fast torrent
#

oh those negative collider ones?

past cairn
#

yeah, but generally any unity log that is cauded by unity itself and not the game

fast torrent
#

i think those in particular might come from c++ land

past cairn
#

they bypass all loggers and just get writen to disk ๐Ÿ˜…

fast torrent
#

@trail jolt spent a fat minute looking for them and i did too

past cairn
#

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

trail jolt
#

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

amber hornet
#

getting some errors here, might be this mod

past cairn
#

#modding-general message

past cairn
#
[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

past cairn
#

Version 1.4.0

  • added timestamps to BepInEx logs
  • Frankenstein patch the stacktraces to hide AsyncLogger from them
#

๐Ÿ˜… .

vestal pebble
#

i must thank asyncloggers

#

for one thing that asyncloggers isnt supposed to do

#

displaying the win32 error that entity got

past cairn
#

๐Ÿ˜‚๐Ÿ˜…

past cairn
#

@rancid parcel would you prefer this kind of counter as timestamp instead?

rancid parcel
#

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

past cairn
#

no it's a global counter atomically incremented each time a log call happens

rancid parcel
#

oh, huh

#

I assumed it wasn't that since it skipped straight to 64 in your screenshot

past cairn
#

not all logs end up being written

#

unity gobbles some normally

rancid parcel
#

ah, I see

#

well anyway, I wouldn't worry about implementing that anyway

past cairn
#

i mean it's already on github, just did not feel was worth a release yet

rancid parcel
#

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 WAYTOODANK

past cairn
#

using this number you'll be 100% sure the order is correct.. each number will be unique and increasing

rancid parcel
#

yeah, that's definitely good

past cairn
#

with both ticks and date there is some cases where multiple log lines have the same timestamp

rancid parcel
#

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

past cairn
#

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

rancid parcel
#

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

past cairn
#

we may make a custom diskListener to write the logs in order ๐Ÿค”

rancid parcel
#

thonk what's that

#

oh you mean the BepInEx thing?

past cairn
#

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

rancid parcel
#

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

past cairn
#

it makes sens because they are listening to events, but if you do not know that, they would be better names as Writers

rancid parcel
#

sure, but their purpose isn't to listen to events

past cairn
#

it is, they are listening to log events

#

either from unity or mods

rancid parcel
#

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

past cairn
#

true

past cairn
#

@rancid parcel
what about dumping them in a sqlite db ๐Ÿ˜

#

as always asynchronously to never halt the game

fickle elm
#

I have insane fps drops while scanning 17k loot on the ship after the last update with Shiploot enabled

past cairn
#

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 ๐Ÿค”

past cairn
#

try downgrade the mod or remove it but i doubt it's caused by AsyncLogger

fickle elm
#

Ok, i'll try later

rancid parcel
past cairn
#

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

rancid parcel
#

possibly, yeah

#

or they'll just get confused and ask which one lol

past cairn
#

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...

undone obsidian
rancid parcel
#

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

past cairn
#

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

rancid parcel
#

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

past cairn
#

but wasn't your issues exaclty that the native ones were not in order? XD

rancid parcel
#

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

undone obsidian
#

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.

rancid parcel
#

people often share logs from the console as well

undone obsidian
#

True

rancid parcel
#

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

past cairn
undone obsidian
#

It really wouldn't affect "performance" if it would be done only on game exit, but it wouldn't solve other issues.

past cairn
#

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 ๐Ÿ˜…

fickle elm
#

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

grizzled jacinth
fickle elm
#

Nah, same issue with v1.0.0 ShipLoot

#

ShipLootPlus works fine, but has problems with micro stuttering when picking up or dropping items

vestal fox
#

why does async and shiploot conflict to the point where you stutter at like 3 fps?

grizzled jacinth
#

ShipLoot is barely supported, and even the dev said it's code is kind of messy and hacked together lol

vestal fox
#

"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.

past cairn
#

i'll push v1.5.0 soon with a Config option ( off by default ) for them

past cairn
idle cloud
#

whats new in 1.5.0?

past cairn
#

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

idle cloud
#

oh thats actually very gud to hear

#

thx big lot ๐Ÿ‘

wicked coral
past cairn
#

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 ๐Ÿ˜…

wicked coral
#

oh true....

rancid parcel
#

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

past cairn
#

no i was creating a stacktrace for each generated log

rancid parcel
#

wouldn't it be retrieving the same stack traces without async?

#

oh thonk

#

that'll do it for sure lol

past cairn
#

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

rancid parcel
#

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

past cairn
#

sry ns

rancid parcel
#

ah

past cairn
#

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

rancid parcel
#

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?

past cairn
#

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

rancid parcel
past cairn
#

yes

past cairn
rancid parcel
#

oh, I guess that original stack trace is caught on the native side and rethrown at the source of the network message?

past cairn
#

the stacktrace is generated on the native side yeah, it does not matter where the exception generated

rancid parcel
#

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

#

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

grizzled jacinth
past cairn
past cairn
#

maybe there is a way to make it cache the stacktrace preventively

past cairn
#

nope ๐Ÿ˜ž

fickle elm
grizzled jacinth
fickle elm
#

Now there are problems with ShipLootPLUS, save files take much longer to load lol

grizzled jacinth
#

๐Ÿ˜‚

#

What did you do?

#

Lmfao

past cairn
#

i can't even reproduce it... it happens randomly reeee

grizzled jacinth
past cairn
#

not the timeout but the delay ( which is the time my mod waits between a completed connection and the start of the next one )

grizzled jacinth
#

it's set to 5 seconds right now right? Maybe I should set it to 10?

past cairn
#

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

grizzled jacinth
#

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

past cairn
#

yes try increasing it at steps and eventually you'll find a value that works

past cairn
#

20k on ship

mental orchid
#

planned group run usually gonna need wider gap broiled

#

everyone went MINE MINE

past cairn
#

??

mental orchid
#

the queue

#

i see so many times people joining at the same time that funky stuff happens

past cairn
#

hopefully MC update will fix those issues

#

this numbers are fantastic. i'm so glad people are liking my mod

fickle elm
tepid nova
#

Your mod is awesome, I hope you hit a mil!

grizzled jacinth
#

@past cairn so why was the sqlite stuff added btw?

past cairn
#

for mod devs to be able to sort the logs in the order they actually generate

grizzled jacinth
#

ah

past cairn
#

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

grizzled jacinth
#

Did you find out why your mod dislikes the ShipLoot mods btw?

past cairn
#

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

sturdy apex
#

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)

past cairn
#

@rancid parcel here they come again ๐Ÿ˜‚๐Ÿ˜ญ

sturdy apex
#

Sorry is my problem is stupid...

past cairn
rancid parcel
past cairn
#

both the ExceptionDispatchInfo and the rethrown exception

rancid parcel
#

ah, that's frustrating

#

I gotta figure out how the inner exception's stack trace stays

tepid nova
#

For the sqlite database, can you pull in the mods that the user has installed into another table?

past cairn
#

uhh sure that should be possible

tepid nova
#

Idk, was just a thought. That way debugging for devs might be easier with just the one file.

past cairn
#

i mean tecnically the logs already have the modlist in them but a nicely ordered table definetly is a plus

tepid nova
#

That's true!

past cairn
#

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

grizzled jacinth
#

@past cairn can confirm the sqlite file being written makes performance worse

grizzled jacinth
#

It wasn't Async Loggers, was another mod bugging out

wicked coral
#

matty getting strays left and right

past cairn
#

Event API is almost ready ๐Ÿ˜„ will first go to an Experimental TS release

past cairn
past cairn
#

i will add more documentation in the future, this is just to gather some feedback ๐Ÿ˜ฌ

grizzled jacinth
past cairn
#

yes, i 100% dont want any random downloading it thinking it's the official one and complain it is breaking stuff ๐Ÿ˜…

grizzled jacinth
#

๐Ÿ˜‚

past cairn
# past cairn # [Experimental release of v1.6.0](<https://thunderstore.io/c/lethal-company/p/m...

adding a bit of documentation:
this release adds a softDependable API to allow mods to write two kinds of extra information:

  • events using the WriteEvent(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 reference
  • modData using the WriteData(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

past cairn
#

there is also an example ProxyFile that i mentioned in the README but probably should also link it here

past cairn
#

as i havent got any feeback. i decided to go though anyways and release the update to the main branch anyways

rancid parcel
#

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

past cairn
#

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 ๐Ÿค”

rancid parcel
#

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

past cairn
#

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

rancid parcel
#

timestamp ranges in really large log files will be useful certainly

past cairn
#

yeah the bigger the modpack the larger the log files will be

#

so having timestamps and easy navigability is really usefull

flat rune
#

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)
past cairn
#

uh they should not be happening... i need to investigate this

vestal pebble
#

i'm not getting the sqlite even with it enabled?

past cairn
#

are you on a different os?
linux / windows x32?

vestal pebble
#

windows 10 pro

past cairn
#

mmm are you searching where you normally find the LogOutput.log?

vestal pebble
#

yeah

past cairn
#

that's really weird can you send a picture of the folder with the LogOutput.log file?

vestal pebble
grizzled jacinth
past cairn
#

that's not the LogOutput.log folder

vestal pebble
#

oh?

#

where is it then

grizzled jacinth
#

it'll be in Browse profile Folder

#

then your profile

past cairn
#

you'll find it in the profile folder under /BepInEx

vestal pebble
#

ohh

#

thx

#

mb

grizzled jacinth
#

Also I personally disabled the DbLogging on my end

#

It causes stutters

vestal pebble
#

yeah i'm just using it for my pack for now

vestal pebble
#

i'll remove it once i get my pack finished

past cairn
grizzled jacinth
vestal pebble
#

also then what's the difference between the logoutput and player.log?

past cairn
#

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

vestal pebble
#

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

past cairn
#

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

past cairn
grizzled jacinth
past cairn
#

placebo ๐Ÿคฆ

tepid nova
#

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.

past cairn
#

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 )

wicked coral
#

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

past cairn
#

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

kind steeple
#

@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?

past cairn
past cairn
#

but at the moment is not possible

past cairn
short tangle
#

Thanks for the ROUNDS port ๐Ÿซก

kind steeple
#

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

past cairn
#

the problem with using an interface is that it will require other mods to hard depend on AsyncLoggers

grizzled jacinth
#

It used to show in the config but looks like you removed it

past cairn
#

how do you implement an interface if you do not reference it?
and how do you reference it if the dll is missing?

kind steeple
#

You're right - I thought I had tested something but clearly not

past cairn
#

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

kind steeple
#

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

wicked coral
past cairn
#

neither was i but then i was proven wrong ๐Ÿ˜…

flat rune
#
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?

past cairn
#

yeah seems so... not a big issue so i will fix it next release

cunning meadow
#

Hey

#

I might be having an issue with Async Loggers

#

Ill return in 5 minutes to confirm

kind steeple
#

@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

rancid parcel
#

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

kind steeple
#

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

rancid parcel
#

ahh, I see, that's cool

tepid nova
#

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

past cairn
#

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

tepid nova
#

Copy that! Thank you.

inner ocean
#

Does this work with v50?

grizzled jacinth
#

Yes

formal coral
#

can someone dumb this mod down for me

stray tundra
#

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. yoiled

#

i hope this is an apt explanation. now go download async logger. alright

wicked coral
#

that brain cell analogy is hilarious ๐Ÿคฃ

#

run good mean happy gamer

wicked coral
past cairn
#

@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 ๐Ÿค”

kind steeple
past cairn
#

yeah i saw that but i want to experiment a bit more with it before using

kind steeple
#

Ah okay

#

is ILogListener your interface or bepinex's - I can't remember

past cairn
#

BepInEx

kind steeple
#

๐Ÿ‘

#

I'll follow this convention then

past cairn
#

yeah was about to say it. as the mod is fully a preloader

#

it will not show up in the BepInEx modlist

kind steeple
#

won't be able to give it a go just yet but will do

past cairn
#

at runtime

kind steeple
past cairn
#

you need to use something like the integration i published for the DBAPI

kind steeple
#

the important part is the [MethodImpl]

#

Oh I see

past cairn
#

yeah method impl but the issue is the Enable

kind steeple
#

You're saying I won't be able to query the chainloader to see if your mod is present

past cairn
#

it will walways return false

kind steeple
#

Aye

past cairn
#

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

kind steeple
past cairn
#

not super elegant but does the job

past cairn
#

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

kind steeple
cunning meadow
#

@summer flare

past cairn
#

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 ๐Ÿ˜…

rancid parcel
#

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

past cairn
#

uh nope still our implementation

rancid parcel
#

oh ok

past cairn
#

casue the system library is slower

rancid parcel
#

oh is it? the specific one that they suggested you mean?

past cairn
#

too much object overhead apparently for making it work as a generic

#

yeah

rancid parcel
#

ah, huh

#

okay interesting

past cairn
#

has the same perofrmance as a normal Queue unles you're in the milion entires

rancid parcel
#

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

past cairn
#

i mean i tried to run it on my Cenntrino Duo old pc... but let alone Async not even vanilla LC booted ๐Ÿ˜‚

rancid parcel
#

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

past cairn
#

Affininty 4 works fine ๐Ÿค”

rancid parcel
#

I wonder if this person's dual core is hyperthreaded though

past cairn
#

even affinity 1 ( only core 0 ) works

#

albeit really slow

rancid parcel
#

hmm

past cairn
rancid parcel
#

maybe it's something with the mods then thonk

#

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

past cairn
rancid parcel
#

lol oof

past cairn
#

i mean this game ( and basically any other game exept mc ) are not really meant to work in a single core single thread scenario

rancid parcel
#

yeah it makes sense

#

makes me wonder what it's threading though, Unity itself doesn't really encourage multithreading

past cairn
#

but still does it behind the scenes with his Jobs

rancid parcel
#

yeah

#

I suppose a lot of it could be loading assets in jobs

past cairn
#

am i wrong @wicked coral?

past cairn
#

@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 ๐Ÿ˜…

wicked coral
#

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

past cairn
#

i haven't been able to reprodce the problem even when limiting LC to a single core and single thread ๐Ÿ˜‚

past cairn
#

still boot times with 1 thread are sooo bad ๐Ÿ˜‚

wicked coral
#

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

past cairn
#

yeah.. i'm surprised the game even boots

wicked coral
#

lmfao it sounds rough for sure

past cairn
#

i mean i tried to run it on my Cenntrino Duo old pc... but let alone Async not even vanilla LC booted

wicked coral
#

true old pcs arent gonna have a good time modded or not

rancid parcel
past cairn
#

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

rancid parcel
#

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

real juniper
#

this is ok?

past cairn
#

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

amber hornet
#

I am using AdditionalNetworking Experimental and i think that makes bees from beehive invisible

#

this is the error i can see

#

and this

past cairn
#

as before have you tried removing it and see if you still have issues?

amber hornet
#

i will check

amber hornet
#

now i got something relevant to additionalnetworking

past cairn
#

you're throwing out items so fast that the mod is not able to keep up ๐Ÿ˜‚

amber hornet
#

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

amber hornet
#

back again with some errors for additional networking

past cairn
#

O.o

real juniper
#

without morecompany normal fine no Error AsyncLoggers

past cairn
past cairn
real juniper
kind steeple
amber hornet
past cairn
#

now it's the on destroy ๐Ÿ˜‚๐Ÿ˜…

cunning meadow
#

@past cairn assuming this and Lobby Control are v50 compat, how about your other mods?

rancid parcel
#

async loggers absolutely is

#

it doesn't do anything with Lethal Company

cunning meadow
#

ok

past cairn
#

๐Ÿ˜….

past cairn
#

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

rancid parcel
#

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

wicked coral
past cairn
#

no, no corruption but in case of crash all not yet written logs are lost

rancid parcel
#

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

past cairn
#

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 ๐Ÿ™ƒ

rancid parcel
#

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

lean kiln
#
[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

past cairn
#

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

deep torrent
#

thej01-FearOverhauled icon
FearOverhauled (I have no idea why this was sent at all lmao)

past cairn
#

โ“

stray tundra
#

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

past cairn
#

not really, the browser program should tell you what the error is if there is any ๐Ÿค”

fringe basin
#

I think Async threw these errors and I don't know what they are related to

past cairn
fringe basin
#

Nope, but I'm using BepInEx 5.4.23.2

past cairn
#

i mean do you have it as a dependecy of another mod?

#

or you have only Bepinex and AsyncLoggers in the pack?

fringe basin
#

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

past cairn
fringe basin
#

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

past cairn
#

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

fringe basin
#

And not consistently at that. This error occurred at the launching phase of the game.

gaunt iron
#

We need that from the OLDER .NET versiosn, this is when it's a no-op in .NET > 4 ^

past cairn
#

this rethrows the eception tho ๐Ÿค” , the unity call is just feeding it to a lower level c function

gaunt iron
#

ExceptionDispatchInfo exists in .NET > 4 for example, but in Unity we're .NET Framework 2.1 ofc.

past cairn
#

i probably need to do a funky

try{
    rethrow
}catch(){
   orig()
}````
gaunt iron
# past cairn this rethrows the eception tho ๐Ÿค” , the unity call is just feeding it to a lower...
#

Shows taking exceptions from one thread and displaying them on another, with the original stack trace preserved

gaunt iron
past cairn
#

i tried the ExceptionDispatchInfo too.. it did not work

#

seems that the c part of unity appends the caller stack to the exception stack

gaunt iron
past cairn
#

yeah wrapping exceptions in exceptions

#

the "preserveStackTrace" route i need to test

gaunt iron
#

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);
}
past cairn
#

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)));
        }
gaunt iron
#

ugh Hub -> IHub -> ? -_- seems like a loop trying to trace that, either way, we had examples before.

gaunt iron
past cairn
#

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 ๐Ÿค”

past cairn
#
        internal static readonly FastInvokeHandler preserveStackTrace = MethodInvoker.GetHandler(AccessTools.Method(typeof(Exception),"InternalPreserveStackTrace"));

love to mix and match utilities ๐Ÿคฃ

#

Nope still the same result :/

past cairn
#

by default all is allowed so logs will follow whatever is in the BepInEx config

mental orchid
#

cuz theres some mod that just like to spam

past cairn
#

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 )
mental orchid
#

i think this is more user friendly than logneuter in a way

#

which is ๐Ÿ”ฅ

past cairn
#

this targets entire mods, logneuterer is more precise and targets specific log messages

mental orchid
#

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

past cairn
#

i mean it originally was desinged to target the basegame logs... i'm not sure why people started using it for modded logs too

mental orchid
#

umm,, cuz theres config for it ? imhuhimwuh unless i was thinkin wrong on how it works

past cairn
#

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

mental orchid
#

alright ohhh ok noted

mental orchid
#

im turning these to false
but the log still showing them?
or im i getting this wrong again imhuhimwuh

past cairn
#

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

mental orchid
#

ok it worked for diversity
so whats 3rd logger again?

mental orchid
#

and will u add block console logging next

past cairn
#

you see 2 entries for ReservedItemCore

a 3rd logger would mean a 3rd entry

past cairn
mental orchid
# past cairn wdym?

setting things to false prevent it from being written in the log file, but not on the console when playing the game

past cairn
#

that's counter intuitive, you always want the more verbose one to be on file

mental orchid
#

now that i think about it thats tru broiled

past cairn
#

and you can do that with normal BepInEx config

mental orchid
#

i guess i can do with that

#

its this one right

real juniper
past cairn
#

even in v1.1.1?

#

i know v1.1.0 was flawled

real juniper
#

now is normal version 1.1.2. version 1.1.1 make cpu 100% e.e

past cairn
#

i mean v1.1.2 def has a big improvement by using semaphores to avoid busy waiting but still

short tusk
#

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

past cairn
#

if you can give me a stacktrace or dump to work with ๐Ÿค”

short tusk
#

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.

flat rune
#

@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

past cairn
#

thanks @flat rune ๐Ÿ˜…

short tusk
past cairn
#

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

past cairn
#

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 )

raw shuttle
#

yey

past cairn
#

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

past cairn
# raw shuttle yey

i heard you complain that stacktraces were a mess with AsyncLoggers ๐Ÿ˜…

raw shuttle
#

a lil bit

visual silo
past cairn
#

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

visual silo
past cairn
#

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 )

past cairn
#

this is going to be a pain.. and i put myself into it w/o anybody asking ๐Ÿ˜ญ

rancid parcel
#

are you trying to patch em all to use BepInEx loggers or something?

past cairn
#

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

past cairn
#

BepInEx works!

#

Throthling works unless it's a really complex logCall :/

#

toughts on this config format?

past cairn
past cairn
#

as mentioned before it's just a bool toggle but most people would prefer performance to be the default

raw shuttle
#

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

past cairn
#

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

raw shuttle
#

I rarely use the unity player log so that's probably fine

past cairn
#

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
past cairn
#

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

past cairn
short tusk
past cairn
#

this going to take a while to import ๐Ÿ˜…

short tusk
past cairn
#

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 ๐Ÿคญ

short tusk
#

oh

past cairn
#

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

past cairn
#

@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>
carmine crystal
#

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?

past cairn
#

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()
grizzled jacinth
past cairn
#

i see why ๐Ÿคฃ

carmine crystal
#

yeah ๐Ÿ˜ญ

#

just saw that too LOL

#

removing the IL code for the logs should fix it then

past cairn
#

this means you are also incompatible with LogNeuterer btw

carmine crystal
#

don't really need to transpile it but without that vanilla will throw false error messages I can't really do much about iirc

past cairn
#

just nobody ever cared about patching thoose calls out

carmine crystal
#

I'll fix it and upload a fix shortly

#

I hate transpilers LMFAO ๐Ÿ˜ญ

past cairn
#

ohh you're wrapping the error calls in a if to skip them

carmine crystal
#

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

past cairn
#

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

carmine crystal
#

oopsies ๐Ÿ˜Š

#

I'll go through and fix it in a bit LOL

carmine crystal
#

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

rancid parcel
#

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

past cairn
rancid parcel
#

ah right, forgot about that

past cairn
#

and for who likes to mess around with stuff, please try the logWrapper settings ๐Ÿ˜„

past cairn
kind steeple
#

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)

past cairn
#

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

past cairn
kind steeple
#

yeah

#

something like that

#

uhhh

#

no not really

#

uhhhhhhhhhhhhhhhhhhhhhhhhh

#

maybe

#

I am unsure ๐Ÿ˜‚

past cairn
#

i mean i could but why would you? if you're writing a new LogListener just make a separate async one instead ๐Ÿค”

kind steeple
#

OK, I don't see why it needs to be AsyncLogEvent

past cairn
#

and tell AsyncLoggers to not wrap it

kind steeple
#

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

past cairn
#

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

kind steeple
#

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

past cairn
#

that's not something your listener will ever see or feel tho

past cairn
#

if your listener does that then it indeed is async? whst do you mean with it needing to be called "sync"?

kind steeple
#

why are you putting 'sync' in quotes, that's the terminology

#

i wouldn't put 'async' in quotes

past cairn
#

any async call by definition will be requested from a sync one ๐Ÿ˜…

kind steeple
#

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

past cairn
#

if you await an async taks youre just making it become sync tho ๐Ÿค”

kind steeple
#

yes, that's what I want in this case - the main thread should block until the queue accepts the log message

past cairn
#

i'm sorry you're loosing me in technicalities ๐Ÿ˜‚๐Ÿ˜…

kind steeple
#

๐Ÿ˜‚

kind steeple
#

Surely you have a similar thing for async loggers ?

#

to ensure log messages keep order?

past cairn
#

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

kind steeple
#

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

kind steeple
past cairn
#

same as before it's a public method on the main class
i've also added a brief description in the README

#

https://github.com/mattymatty97/LTC_AsyncLoggers/blob/rewrite/AsyncLoggers%2Fsrc%2FAsyncLoggers.cs#L152-L204

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 ๐Ÿค”

kind steeple
#

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 ๐Ÿ˜…

past cairn
#

๐Ÿค” 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

past cairn
#

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
past cairn
kind steeple
#

and also, 1 method for consumers is nicer than 3 ๐Ÿ˜…

past cairn
#

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

kind steeple
#

do you mean descriptively named (by extensive)?

past cairn
#

single method to do everything vs many methods that each does something different

kind steeple
#

ah, I see

#

functions in general sould 'do one thing, do it well, do it tell'

#

API functions included

past cairn
#

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

kind steeple
#

but equally, don't have 10 functions that do the same thing, where you could have 1 function with an extra parameter

kind steeple
past cairn
#

but i can see how it would be cleaner in this instance to have a single method and use a flag system

kind steeple
#

โค๏ธ

#

yeah in the implementation you can still do

#
if (hasOneFlag) addToOneSet()
if (hasTwoFlag) addToTwoSet()
#

if that's your preference

past cairn
#

yeah that's what I'm going to do

kind steeple
#

In terms of asymptotic complexity, there is no difference between getting from dictionary plus doing the has flag computation, and the set .contains

past cairn
#

parse the flag immediately in the method and add stuff to the sets depending on it

kind steeple
#

in terms of actual time / instructions - there will be a difference - but I think it would probably be negligible

past cairn
#

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

kind steeple
#

The time taken to hash the whatever it is for the dictionary/hashset lookup will far outweigh the binary AND and brnull

past cairn
#

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 ๐Ÿ˜…

kind steeple
#

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

past cairn
#

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

kind steeple
past cairn
#

@kind steeple how's this as an EntryPoint?

kind steeple
#

This looks good to me

#

TraceableLevelsMaks?

#

is that a partial translation ?

past cairn
#

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 ๐Ÿ˜„

raw shuttle
#

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

rancid parcel
#

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

raw shuttle
#

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

rancid parcel
#

not sure if there's any way to access it in a managed context, but I suppose maybe there is some way

raw shuttle
#

bleh

past cairn
#

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>
past cairn
# past cairn purely cosmetic question ๐Ÿ˜… which version is better: ```xml <LogCall obsolete="...

let me reword the question:
In the case of Static Methods is it better to:

  1. print only the Method name ( eg: Format("formatting string", args))
  2. print only the Class name and Method name ( eg: String.Format("formatting string", args))
  3. 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

past cairn
#

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

past cairn
#

@pulsar forum are you trying to start multiple instances?

pulsar forum
#

yeah

past cairn
#

if so just disable

#

only one instance can access the sqlite file sadly

pulsar forum
#

Yeah

past cairn
#

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

pulsar forum
#

๐Ÿ‘

#

I would like if the default was Fatal, Error, Warning, Message, Info

past cairn
#

if you dont want debugs globally just disable them from bepinex config as this mod works on top of it

pulsar forum
#

I want debug from one mod specifically

past cairn
#

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 ๐Ÿค”

pulsar forum
#

it doesn't seem to hide these messages though

past cairn
#

weird they shold be hidded ๐Ÿค”

past cairn
#

ik gale does not write it to config until you either click out of the config tab or click on a different setting ๐Ÿค” x2

pulsar forum
#

It writes with every change

past cairn
#

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

pulsar forum
#

huh ok

#

I'm pretty sure that wasnt happening though

#

since wouldn't info messages also be there in that case?

past cairn
#

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 ๐Ÿ˜…

#

the filter is read based on the SectionName and is just put in a bitwise and with the loglevel of the event

past cairn
mental orchid
#

o0oOOoOOOOO

mental orchid
grizzled jacinth
#

All I thought of when you said that

#

LOL

high bobcat
#

So, my game is not writing any logs to Disc whatsoever, as I disabled logs and stuff. Do I still need this mod?

past cairn
#

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 )

high bobcat
#

Should I keep "do not collect stack traces" disabled to ensure better performance

#

Should I keep LogWrapping enabled to ensure better performance?

past cairn
#

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

high bobcat
#

@past cairn Could you explain what the AsyncLoggersLogLevels config does? like, if I disabled a source to write logs, would that mean better performance?

past cairn
#

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 ๐Ÿ˜…

mental orchid
#

where do i find this ?

high bobcat
high bobcat
#

Does disabling showing the console for log output increase performance?

#

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

past cairn
#

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

high bobcat
#

Thank you

past cairn
#

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
desert oriole
#

i have been getting this error for some reason

past cairn
#

the database got corrupted... did you have hard crashes by chance?

desert oriole
#

yes

#

i already tried reinstalling as it would not launch with the mod enabled at all

past cairn
#

in your profile folder ( where you have LogOutput.log ) find and delete LogOutput.sqlite and derivates

#

or just make a new profile

past cairn
#

no problem

#

have fun playing

past cairn
#

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

past cairn
lone stone
#

What does intercept unity logs do?

past cairn
#

BepInEx only shows unity Logs from the main thread

rancid parcel
#

ooh nice

past cairn
#

if a Worker thread sends logs they are only visible in Zeekers/Unity " Player.Log"
AsyncLoggers catches logs from other threads too now

rancid parcel
#

definitely would have helped at the point where I was under the impression that it should have logged things lol

past cairn
#

well once TS allows the package back on the platform

lone stone
#

That sounds really helpful

rancid parcel
#

I forget if there's something that even Player.log misses though

past cairn
#

i got the pages delisted rn ๐Ÿ˜…

lone stone
#

I know there were a few times when I was debugging stuff and it only showed in player.log

past cairn
#

player.log currently shows also the normal Console.Out.Writes

lone stone
#

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

past cairn
#

sadly it's not that simple to differentiate them :/

past cairn
#

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 ๐Ÿ˜ญ

flat rune
#

You can patch it, but you need to wait when Initialize is completed

grizzled jacinth
lone stone
#

i just tried out the experimental version rn

grizzled jacinth
#

I tested it earlier and I can notice the performance increase

lone stone
#

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

grizzled jacinth
#

Oh fun

grizzled jacinth
#

the game generally slows down overtime as you play

lone stone
#

i suppose

grizzled jacinth
#

I wanna see if it also breaks LoadingScreen for me too

#

lol

lone stone
#

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

grizzled jacinth
#

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

lone stone
#

it happens so rarely that i dont mind

past cairn
#

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 ๐Ÿ˜…

past cairn
grizzled jacinth
#

@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

lone stone
#

It couldn't be that

grizzled jacinth
#

That shit always reinstalls itself and runs in the background if you don't disable Game Bar with gpedit or smth I found

lone stone
#

I ran Chris Titus' windows utility after it did updates

#

There is no way it would be gamedvr coming back

grizzled jacinth
#

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

past cairn
#

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

lone stone
#

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

past cairn
#

@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 ๐Ÿ˜•

flat rune
#

it's just not possible

flat rune
#

and legacy mono tls provider doesn't support tls1.2/1.3

past cairn
#

uh? have you not done it for FixPluginTypes thing?

flat rune
#

it didn't work

#

hm, actually it did work, but it's just making patching in chainloader initialize

#

so you could try the P/Invoke instead

#

if you're really need that file before unityplayer is loaded

past cairn
#

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 ๐Ÿคฃ

grizzled jacinth
#

โ˜ ๏ธ

proper tundra
#

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

past cairn
#

uh. weird . the BepInEx logs definitely are supposed to show up

#

i'll have to debug that this evening

past cairn
#

@flat rune winhttp.dll works like a charm Prayge

#

i'm sorry TS Moderators, AsyncLoggers will trigger so many of your flags from now on ๐Ÿ™ƒ

grizzled jacinth
#

lol