Reports
Pulse Save can write a report for every save and load. A report says which models were processed, how it went for each of them, how long it took, and what the models wrote about it. You look at the reports in the editor tab Pulse Save Reports.
Settings
Project Settings > Pulse > Save > Report
| Setting | Default | Meaning |
|---|---|---|
EditorReportMode | Always | When reports are written in the editor. This covers every build that has the editor: PIE and standalone games started from the editor. |
PackagedReportMode | OnFailure | When reports are written in a packaged game (a build without the editor). |
MaxStoredReports | 50 | How many report files are kept. The oldest are deleted when a new one is written. 0 keeps all. |
The mode is EPulseSaveReportMode:
| Value | Behavior |
|---|---|
Disabled | Nothing is recorded or written. Models do not even store their messages. |
OnFailure | A report is written only if something failed (see below). |
Always | A report is written for every process. |
A report counts as failed if the process did not succeed, a model failed or timed out, or a model wrote an error message (see Messages of a model). Note that FPulseSaveProcessReport::bWasSuccessful only reflects the last chunk of a process, so the report looks at every model.
What is reported
Kind (EPulseSaveReportScope) | Written when |
|---|---|
Process | Once for every Save() / Load() of a save manager. Static models that take part are listed with it. |
SingleObject | For SaveSingleObject / LoadSingleObject. Including calls that fail right away, e.g. because the object has no record. |
StaticModel | For operations on static models outside of a process: GetOrCreateStaticModel (only if it actually loads or creates a model), SaveStaticModel and UPulseSaveUtils::LoadStaticModelFromSlot. |
Single-object and static-model operations are often numerous (think of actors that load themselves when they spawn). They are collected and written as one report after one second without a new operation. They are also written when the manager is destroyed or when you call UPulseSaveManager::FlushReports().
Every model of a report has an entry with:
- identifier, record type (
Collected/Static), model class, - result:
Succeeded,Failed,TimedOutorSkipped(identifier missing or duplicated), the reason, and the duration, - whether its record was migrated, and from which class and version (see Save migration),
- the messages the model wrote.
A report never contains the saved data itself.
Save slot
A report also carries the context of its manager: a free text that tells managers apart, because their object names are generated. Call UPulseSaveManager::SetReportContext("Player profile") (Blueprint: Set Report Context), or create the manager with Pulse::Save::CreateManager(Context). The context is shown in the Manager column, in the details and in the search of the editor tab. Unlike the slot it is kept when the save game is replaced, and it applies to reports that start afterwards.
A report also names the save slot the manager worked with (SlotName, and SlotEntry for slots with entries). It is shown in the list, in the details and in the search of the editor tab.
SaveToSlot,LoadFromSlot, the...ByNamevariants andSaveToEngineSlot/LoadFromEngineSlotset it automatically.- If you handle slots yourself and call
Save()/Load()directly, callUPulseSaveManager::SetReportSlot(SlotName, EntryId)(Blueprint: Set Report Slot).GetReportSlotName()returns it. - The slot belongs to the save game:
SetSaveGameandClearSaveGameforget it, so callSetReportSlotafterSetSaveGame. This keeps a report from showing the slot of a save game that is no longer loaded. - Single-object and static-model reports carry the slot that was set when they were collected. If the slot changes, what was collected before is written first.
UPulseSaveUtils::LoadStaticModelFromSlothas no manager, so its report names the slot it read from.- The slot is empty if nothing set it.
Messages of a model
A model can write messages into the list that goes into the report. This is also possible for models that succeed.
| C++ / Blueprint | Meaning |
|---|---|
LogInfo(Message) | Information that helps to understand what happened. |
LogWarning(Message) | Something unexpected that did not stop the model. |
LogError(Message) | Something went wrong. |
They are available on every model (UPulseSaveModelBase). Call them from the hooks of a model, from IPulseSaveInterface::OnSave / OnPostLoad (they receive the model as a parameter), or from a migration (Context.NewModel). In Blueprint they are normal nodes (“Log Info”, “Log Warning”, “Log Error”).
- The messages are also written to the log (
LogPulseSave). - A model that wrote at least one error counts as faulty in the report and makes the report count as failed. It does not change the result of the process:
bWasSuccessfuland the completion callbacks stay as they are. - Infos and warnings never make a model faulty.
- A model stores at most 100 messages per operation. The rest is counted (
DroppedMessageCount). - Messages are only stored if reports are not
Disabledin the current build.
The editor tab
Open it with the console command PulseSave.OpenReports, or from the editor menu that lists the tabs, where it is registered in the Developer Tools group as Pulse Save Reports.
- Left: the list of reports, newest first, with result, time, kind, manager, number of models and number of faulty models. Search, “Only failed” and a filter by kind narrow it down.
- Right, top: the details of the selected report: result, kind, time, manager, world, build, duration, and the counters (records, static models, migrations, skipped, timeouts).
- Right, bottom: the models, split into two views:
- Faulty models: models that failed, timed out or wrote an error.
- Succeeded models: all others, including skipped ones.
Every model is one row with type, result, class, duration and number of messages. Expand it to see the reason of a failure, its details (record type, class, duration, migration) and the messages it wrote, colored by severity. Models that failed or wrote messages start expanded. Search and the Info / Warnings / Errors switches filter the models and messages. The context menu copies a row or all messages of a model.
- Toolbar: Refresh, Open Folder, Open File…, Delete, Delete All.
- The tab updates by itself when a report is written in the running editor (PIE). Reports written by another process appear after Refresh.
Reports of a packaged game
In a packaged game reports are written to <Project>/Saved/PulseSave/Reports of the installed game (by default only for failures). To look at one in the editor, copy the file to your machine and use Open File…. Reports of another plugin version (the file has a reportVersion) are not opened.
Files
Reports are JSON files in <Project>/Saved/PulseSave/Reports, named yyyyMMdd-HHmmss-fff-####_<Kind>_<Save|Load>_<Manager>_<Ok|Failed>.json. They are written in the background. The directory can be found with Pulse::Save::Report::GetReportDirectory(). To react to a new report in code, bind IPulseSave::Get().OnReportWritten() (file path, whether the report has failures). Pulse::Save::Report::EnumerateReportFiles and LoadReportFromFile read them again.