From 24d844dcbddb6d524d1d068cbf736ba0c9c83908 Mon Sep 17 00:00:00 2001 From: Pierre Baron Date: Fri, 5 Sep 2025 14:00:46 +0200 Subject: [PATCH 1/6] feat: add log for SRUM --- thorlog/v3/systemresourceusagemonitor.go | 86 ++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 thorlog/v3/systemresourceusagemonitor.go diff --git a/thorlog/v3/systemresourceusagemonitor.go b/thorlog/v3/systemresourceusagemonitor.go new file mode 100644 index 0000000..8741b34 --- /dev/null +++ b/thorlog/v3/systemresourceusagemonitor.go @@ -0,0 +1,86 @@ +package thorlog + +import ( + "time" + + "github.com/NextronSystems/jsonlog" +) + +// SRUMEntry holds information about a single entry of a System Resource Usage Monitor (SRUM) +// database. These databases are written by the SRUM service which collects and aggregates +// system resource usage data such as network activity, energy consumption, and application usage. +// +// Reference: https://www.forensafe.com/blogs/srudb.html +// +// A SRUMEntry represents a single entry in the "Application Resource Usage" table. +// Enriched with AppInfo, UserSID and UserName from the "SruDbIdMapTable" table. +// +// Columns in {D10CA2FE-6FCF-4F6D-848E-B2E99266FA89} (19): +// Id Name Type +// 2 TimeStamp DateTime +// 3 AppId Signed long +// 4 UserId Signed long +// 5 ForegroundCycleTime Long long +// 6 BackgroundCycleTime Long long +// 7 FaceTime Long long +// 10 ForegroundBytesRead Long long +// 11 ForegroundBytesWritten Long long +// 15 BackgroundBytesRead Long long +// 16 BackgroundBytesWritten Long long +// +// Columns in SruDbIdMapTable (3): +// Id Name Type +// 1 IdType Signed byte +// 2 IdIndex Signed long +// 256 IdBlob Long Binary + +type SRUMEntry struct { + jsonlog.ObjectHeader + + // TimeStamp is when the entry was recorded. + TimeStamp time.Time `json:"timestamp" textlog:"timestamp"` + + // AppId is the numeric identifier of the application. + AppId uint32 `json:"app_id" textlog:"app_id"` + + // AppInfo is the Appname/Apppath decoded from the IdBlob + AppInfo string `json:"app_info" textlog:"app_info"` + + // UserId is the numeric identifier of the user. + UserId uint32 `json:"user_id" textlog:"user_id"` + + // UserSID is the string SID parsed from the binary SID + UserSID string `json:"user_info" textlog:"user_info"` + + // UserName is the Username looked up from the SID + UserName string `json:"user_name" textlog:"user_name"` + + // FaceTime is the total foreground time in milliseconds. + FaceTime uint64 `json:"face_time" textlog:"face_time"` + + // ForegroundBytesRead is the number of bytes read in the foreground. + ForegroundBytesRead uint64 `json:"foreground_bytes_read" textlog:"foreground_bytes_read"` + + // ForegroundBytesWritten is the number of bytes written in the foreground. + ForegroundBytesWritten uint64 `json:"foreground_bytes_written" textlog:"foreground_bytes_written"` + + // BackgroundBytesRead is the number of bytes read in the background. + BackgroundBytesRead uint64 `json:"background_bytes_read" textlog:"background_bytes_read"` + + // BackgroundBytesWritten is the number of bytes written in the background. + BackgroundBytesWritten uint64 `json:"background_bytes_written" textlog:"background_bytes_written"` +} + +const typeSRUMEntry = "System Resource Usage Monitor" + +func init() { AddLogObjectType(typeSRUMEntry, &SRUMEntry{}) } + +func NewSRUMEntry() *SRUMEntry { + return &SRUMEntry{ + ObjectHeader: jsonlog.ObjectHeader{ + Type: typeSRUMEntry, + }, + } +} + +func (SRUMEntry) reportable() {} From 966401151072067555f96d5facd8950be8d1a26f Mon Sep 17 00:00:00 2001 From: Pierre Baron Date: Mon, 15 Sep 2025 13:04:04 +0200 Subject: [PATCH 2/6] Remove useless attributes and add 4 new attributes, change entry name. --- thorlog/v3/systemresourceusagemonitor.go | 32 ++++++++++++++---------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/thorlog/v3/systemresourceusagemonitor.go b/thorlog/v3/systemresourceusagemonitor.go index 8741b34..54dd376 100644 --- a/thorlog/v3/systemresourceusagemonitor.go +++ b/thorlog/v3/systemresourceusagemonitor.go @@ -18,15 +18,15 @@ import ( // Columns in {D10CA2FE-6FCF-4F6D-848E-B2E99266FA89} (19): // Id Name Type // 2 TimeStamp DateTime -// 3 AppId Signed long -// 4 UserId Signed long -// 5 ForegroundCycleTime Long long -// 6 BackgroundCycleTime Long long // 7 FaceTime Long long // 10 ForegroundBytesRead Long long // 11 ForegroundBytesWritten Long long +// 12 ForegroundNumReadOperations Long long +// 13 ForegroundNumWriteOperations Long long // 15 BackgroundBytesRead Long long // 16 BackgroundBytesWritten Long long +// 17 BackgroundNumReadOperations Long long +// 18 BackgroundNumWriteOperations Long long // // Columns in SruDbIdMapTable (3): // Id Name Type @@ -40,19 +40,13 @@ type SRUMEntry struct { // TimeStamp is when the entry was recorded. TimeStamp time.Time `json:"timestamp" textlog:"timestamp"` - // AppId is the numeric identifier of the application. - AppId uint32 `json:"app_id" textlog:"app_id"` - // AppInfo is the Appname/Apppath decoded from the IdBlob AppInfo string `json:"app_info" textlog:"app_info"` - // UserId is the numeric identifier of the user. - UserId uint32 `json:"user_id" textlog:"user_id"` - // UserSID is the string SID parsed from the binary SID - UserSID string `json:"user_info" textlog:"user_info"` + UserSID string `json:"user_sid" textlog:"user_sid"` - // UserName is the Username looked up from the SID + // UserName is the Username looked up from the SID, works only on Windows Builds. UserName string `json:"user_name" textlog:"user_name"` // FaceTime is the total foreground time in milliseconds. @@ -64,14 +58,26 @@ type SRUMEntry struct { // ForegroundBytesWritten is the number of bytes written in the foreground. ForegroundBytesWritten uint64 `json:"foreground_bytes_written" textlog:"foreground_bytes_written"` + // ForegroundNumReadOperations is the number of read operations in the foreground. + ForegroundNumReadOperations uint64 `json:"foreground_num_read_operations" textlog:"foreground_num_read_operations"` + + // ForegroundNumWriteOperations is the number of write operations in the foreground. + ForegroundNumWriteOperations uint64 `json:"foreground_num_write_operations" textlog:"foreground_num_write_operations"` + // BackgroundBytesRead is the number of bytes read in the background. BackgroundBytesRead uint64 `json:"background_bytes_read" textlog:"background_bytes_read"` // BackgroundBytesWritten is the number of bytes written in the background. BackgroundBytesWritten uint64 `json:"background_bytes_written" textlog:"background_bytes_written"` + + // BackgroundNumReadOperations is the number of read operations in the background. + BackgroundNumReadOperations uint64 `json:"background_num_read_operations" textlog:"background_num_read_operations"` + + // BackgroundNumWriteOperations is the number of write operations in the background. + BackgroundNumWriteOperations uint64 `json:"background_num_write_operations" textlog:"background_num_write_operations"` } -const typeSRUMEntry = "System Resource Usage Monitor" +const typeSRUMEntry = "SRUM Resource Usage Entry" func init() { AddLogObjectType(typeSRUMEntry, &SRUMEntry{}) } From bb393cc910a8c2f70da02702d8d2fa8286661767 Mon Sep 17 00:00:00 2001 From: Pierre Baron Date: Mon, 22 Sep 2025 09:51:47 +0200 Subject: [PATCH 3/6] Adjust fields and add meaningful comments --- thorlog/v3/systemresourceusagemonitor.go | 54 +++++++++++++++++------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/thorlog/v3/systemresourceusagemonitor.go b/thorlog/v3/systemresourceusagemonitor.go index 54dd376..1d29f02 100644 --- a/thorlog/v3/systemresourceusagemonitor.go +++ b/thorlog/v3/systemresourceusagemonitor.go @@ -12,8 +12,10 @@ import ( // // Reference: https://www.forensafe.com/blogs/srudb.html // -// A SRUMEntry represents a single entry in the "Application Resource Usage" table. -// Enriched with AppInfo, UserSID and UserName from the "SruDbIdMapTable" table. +// A SRUMEntry represents a single entry in the "Application Resource Usage" table +// ({D10CA2FE-6FCF-4F6D-848E-B2E99266FA89}) enriched with AppInfo, UserSID and UserName +// from the "SruDbIdMapTable" table. Each entry represents a snapshot of resource usage +// for a specific application and user combination at a given time. // // Columns in {D10CA2FE-6FCF-4F6D-848E-B2E99266FA89} (19): // Id Name Type @@ -37,43 +39,63 @@ import ( type SRUMEntry struct { jsonlog.ObjectHeader - // TimeStamp is when the entry was recorded. + // TimeStamp is when the resource usage measurement was recorded by SRUM. + // This represents the end time of the measurement period (typically hourly). TimeStamp time.Time `json:"timestamp" textlog:"timestamp"` - // AppInfo is the Appname/Apppath decoded from the IdBlob + // AppInfo contains the application path or executable name extracted from the + // SruDbIdMapTable.IdBlob field. This identifies which application the resource + // usage data belongs to (e.g., "C:\Windows\System32\notepad.exe"). AppInfo string `json:"app_info" textlog:"app_info"` - // UserSID is the string SID parsed from the binary SID + // UserSID is the Windows Security Identifier string parsed from the binary SID + // stored in SruDbIdMapTable.IdBlob. This identifies which user account was + // running the application (e.g., "S-1-5-21-..."). UserSID string `json:"user_sid" textlog:"user_sid"` - // UserName is the Username looked up from the SID, works only on Windows Builds. - UserName string `json:"user_name" textlog:"user_name"` + // UserName is the human-readable username resolved from the UserSID. + // May be empty if the SID cannot be resolved to a username. + UserName string `json:"user_name,omitempty" textlog:"user_name,omitempty"` - // FaceTime is the total foreground time in milliseconds. + // FaceTime is the total time in milliseconds that the application was visible + // to the user (in the foreground) during the measurement period. This indicates + // actual user interaction time with the application. FaceTime uint64 `json:"face_time" textlog:"face_time"` - // ForegroundBytesRead is the number of bytes read in the foreground. + // ForegroundBytesRead is the total number of bytes read from disk/storage + // while the application was in the foreground during the measurement period. ForegroundBytesRead uint64 `json:"foreground_bytes_read" textlog:"foreground_bytes_read"` - // ForegroundBytesWritten is the number of bytes written in the foreground. + // ForegroundBytesWritten is the total number of bytes written to disk/storage + // while the application was in the foreground during the measurement period. ForegroundBytesWritten uint64 `json:"foreground_bytes_written" textlog:"foreground_bytes_written"` - // ForegroundNumReadOperations is the number of read operations in the foreground. + // ForegroundNumReadOperations is the count of discrete read I/O operations + // performed while the application was in the foreground. This differs from + // bytes read as it counts individual operations regardless of size. ForegroundNumReadOperations uint64 `json:"foreground_num_read_operations" textlog:"foreground_num_read_operations"` - // ForegroundNumWriteOperations is the number of write operations in the foreground. + // ForegroundNumWriteOperations is the count of discrete write I/O operations + // performed while the application was in the foreground. This differs from + // bytes written as it counts individual operations regardless of size. ForegroundNumWriteOperations uint64 `json:"foreground_num_write_operations" textlog:"foreground_num_write_operations"` - // BackgroundBytesRead is the number of bytes read in the background. + // BackgroundBytesRead is the total number of bytes read from disk/storage + // while the application was running in the background during the measurement period. BackgroundBytesRead uint64 `json:"background_bytes_read" textlog:"background_bytes_read"` - // BackgroundBytesWritten is the number of bytes written in the background. + // BackgroundBytesWritten is the total number of bytes written to disk/storage + // while the application was running in the background during the measurement period. BackgroundBytesWritten uint64 `json:"background_bytes_written" textlog:"background_bytes_written"` - // BackgroundNumReadOperations is the number of read operations in the background. + // BackgroundNumReadOperations is the count of discrete read I/O operations + // performed while the application was running in the background. This differs + // from bytes read as it counts individual operations regardless of size. BackgroundNumReadOperations uint64 `json:"background_num_read_operations" textlog:"background_num_read_operations"` - // BackgroundNumWriteOperations is the number of write operations in the background. + // BackgroundNumWriteOperations is the count of discrete write I/O operations + // performed while the application was running in the background. This differs + // from bytes written as it counts individual operations regardless of size. BackgroundNumWriteOperations uint64 `json:"background_num_write_operations" textlog:"background_num_write_operations"` } From fc3c7fdd7b67a411e19980cec5ac7c965ed864f2 Mon Sep 17 00:00:00 2001 From: Pierre Baron Date: Mon, 22 Sep 2025 10:33:28 +0200 Subject: [PATCH 4/6] Adjust naming --- thorlog/v3/systemresourceusagemonitor.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/thorlog/v3/systemresourceusagemonitor.go b/thorlog/v3/systemresourceusagemonitor.go index 1d29f02..429a9b0 100644 --- a/thorlog/v3/systemresourceusagemonitor.go +++ b/thorlog/v3/systemresourceusagemonitor.go @@ -6,13 +6,13 @@ import ( "github.com/NextronSystems/jsonlog" ) -// SRUMEntry holds information about a single entry of a System Resource Usage Monitor (SRUM) +// SRUMResourceUsageEntry holds information about a single entry of a System Resource Usage Monitor (SRUM) // database. These databases are written by the SRUM service which collects and aggregates // system resource usage data such as network activity, energy consumption, and application usage. // // Reference: https://www.forensafe.com/blogs/srudb.html // -// A SRUMEntry represents a single entry in the "Application Resource Usage" table +// A SRUMResourceUsageEntry represents a single entry in the "Application Resource Usage" table // ({D10CA2FE-6FCF-4F6D-848E-B2E99266FA89}) enriched with AppInfo, UserSID and UserName // from the "SruDbIdMapTable" table. Each entry represents a snapshot of resource usage // for a specific application and user combination at a given time. @@ -35,8 +35,7 @@ import ( // 1 IdType Signed byte // 2 IdIndex Signed long // 256 IdBlob Long Binary - -type SRUMEntry struct { +type SRUMResourceUsageEntry struct { jsonlog.ObjectHeader // TimeStamp is when the resource usage measurement was recorded by SRUM. @@ -101,14 +100,14 @@ type SRUMEntry struct { const typeSRUMEntry = "SRUM Resource Usage Entry" -func init() { AddLogObjectType(typeSRUMEntry, &SRUMEntry{}) } +func init() { AddLogObjectType(typeSRUMEntry, &SRUMResourceUsageEntry{}) } -func NewSRUMEntry() *SRUMEntry { - return &SRUMEntry{ +func NewSRUMResourceUsageEntry() *SRUMResourceUsageEntry { + return &SRUMResourceUsageEntry{ ObjectHeader: jsonlog.ObjectHeader{ Type: typeSRUMEntry, }, } } -func (SRUMEntry) reportable() {} +func (SRUMResourceUsageEntry) reportable() {} From 292de74ccc951523cdc2c76e51eecf5bf558a2ae Mon Sep 17 00:00:00 2001 From: Pierre Baron Date: Mon, 22 Sep 2025 11:51:23 +0200 Subject: [PATCH 5/6] refactor: facetime type changed to time.Duration --- thorlog/v3/systemresourceusagemonitor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thorlog/v3/systemresourceusagemonitor.go b/thorlog/v3/systemresourceusagemonitor.go index 429a9b0..7d7669e 100644 --- a/thorlog/v3/systemresourceusagemonitor.go +++ b/thorlog/v3/systemresourceusagemonitor.go @@ -59,7 +59,7 @@ type SRUMResourceUsageEntry struct { // FaceTime is the total time in milliseconds that the application was visible // to the user (in the foreground) during the measurement period. This indicates // actual user interaction time with the application. - FaceTime uint64 `json:"face_time" textlog:"face_time"` + FaceTime time.Duration `json:"face_time" textlog:"face_time"` // ForegroundBytesRead is the total number of bytes read from disk/storage // while the application was in the foreground during the measurement period. From a7a73bb6e08c1c8af89c9ab5cff66ffbb8973cd7 Mon Sep 17 00:00:00 2001 From: Pierre Baron Date: Mon, 22 Sep 2025 12:09:03 +0200 Subject: [PATCH 6/6] chore: fix comment --- thorlog/v3/systemresourceusagemonitor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thorlog/v3/systemresourceusagemonitor.go b/thorlog/v3/systemresourceusagemonitor.go index 7d7669e..3680aac 100644 --- a/thorlog/v3/systemresourceusagemonitor.go +++ b/thorlog/v3/systemresourceusagemonitor.go @@ -56,7 +56,7 @@ type SRUMResourceUsageEntry struct { // May be empty if the SID cannot be resolved to a username. UserName string `json:"user_name,omitempty" textlog:"user_name,omitempty"` - // FaceTime is the total time in milliseconds that the application was visible + // FaceTime is the total duration that the application was visible // to the user (in the foreground) during the measurement period. This indicates // actual user interaction time with the application. FaceTime time.Duration `json:"face_time" textlog:"face_time"`