Let me know when you realise...
... that this is a large wall of text. Sorry. :/
There's an object inside the ED API labelled "vanishCounters" which tracks commander logging data. Now, it's not sensible to store that information locally because it can just be edited/deleted, however, it makes sense for your peers to store that information. This information you've either received from my client or from the server when one of us enters the other's instance.
Each key/value pair in this commander logging JSON structure, can store various information. Such as are you friendly? Are you in danger? Etc.
As you may know, if the owner of an instance leaves, ownership is transferred to a new player (if there is no new player, the instance is destroyed), so when you disconnect from the other's instance (in any way) that information is recorded.
You can see what information is recorded just by looking at the ED log files.
[ The following is assumption by experience ]
If you leave either by Waking, Menu > Quit or killing the process the method used is recorded: it won't say "scum pressed Alt+F4

" but it might say "client X timed out" or "client X disconnected; ungraceful exit" or various other informative messages.
This information is submitted to the Frontier server at some point and likely stored in a table that is linked to your commander ID by all the connected peers, or maybe just by the instance holder.
Look at how often ED communicates with the Frontier server, even when you're in an instance alone (Ctrl+B when in game).
When you relaunch the game, your logging data is submitted to the Frontier server, possibly alongside information like "client was terminated by the user."
This can be determined either using the Windows API, or simply from reading a log file. The file could reference an associated crash file if the program crashed, or it could simply not have the entry available which means the program was closed prematurely and didn't crash.
This is three examples of how I'd do it:
{ crash }
[ 01/01/2017 - 22:00 ] [CRASH] Appended by CrashLoggerApp. See crash_log_XYZ.log
// You could put code here to handle crashes. Eg: Run in "safe mode"
[ 02/01/2017 - 09:30 ] [APP_START] Application started. Client reconnected. Logging started.
{ graceful exit }
[ 01/01/2017 - 22:00 ] [APP_EXIT] Client disconnected. Application terminate. Logging stopped.
[ 02/01/2017 - 09:30 ] [APP_START] Application started. Client reconnected. Logging started.
{ ungraceful exit }
[ 02/01/2017 - 09:30 ] [APP_START] Application started. Client reconnected. Logging started.
// The client has determined that there is no [APP_EXIT] or [CRASH] entry in the file. It generates an error code.
[ 02/01/2017 - 09:30 ] [ERROR] No [APP_EXIT] found. No crash log found. Error Code: 5004585
All this information is submitted to the Frontier servers.
If they then compare that data they have against all your previous encounters they will be able to pick up a pattern and -within an acceptable margin for error- make an educated determination as to what happened.
Is it 100% accurate? No.
But patterns don't lie, and if the behaviour is consistent with combat logging. Well, one can normally safely assume this is the case.