Log
Fetch a log of events for a given scope, optionally grouped/sorted/sliced/post-filtered.
The Story So Far...
All necessary updates have been made to the HRMS after the incident at the plant. As part of the investigation behind the incident, an auditor is called over to go through all records with a fine-toothed comb. He is particularly adamant on having access to all historic records and changes over time to make sure no detail, however minute, is missed. Luckily for Eric, his HRMS uses RecallGraph under the hood. Rewinding and replaying historic data is precisely what RecallGraph was built to do!

Before proceeding with this section of the guide, make sure you have understood the concepts of patterns, scopes and paths, explained in the terminology page.
The LOG endpoint is a powerful and flexible querying tool with a huge number of parameter combinations, all of which cannot possibly be explored in this guide. However, hopefully this guide will cover enough ground to make readers comfortable in exploring the rest of the combinations by themselves.
All Events
Overall Count
We don't know which events are of interest to us yet, so we begin with an ad hoc, exploratory analysis to get an idea of the number and types of events in the event log. We will use the GET variant here. The request parameters are shown below:
Param
Value
countsOnly
true
path
/
The result obtained will have a structure as shown below. Your actual numbers may vary. We will shortly see why.
This tells us that there have been a total of 27 events recorded in the system (in the instance from which this result was pulled). That looks a bit strange since we have not performed 27 write operations so far in our walkthrough.
You can also use the POST variant to achieve the same results. In the POST variant, the path and the postFilter parameters are sent in the request body rather than as query parameters. This lets you specify large path patterns and/or filter expressions that would otherwise cause an HTTP 414 URI Too Long exception in the GET variant.
Counts by Type
The root cause behind this anomaly cannot be determined from this singular number. Therefore, we decide to drill down a bit by using a more fine grained grouping clause. We split event counts by event type by using the parameters given below:
Param
Value
countsOnly
true
groupBy
event
path
/
We get the following result:
Now we're getting somewhere. Since we're dealing with a very small dataset, we can easily keep track of how many legitimate create, update and delete operations we should have performed so far. These numbers are:
Expected Entity Creates
Collection
Count
Departments
1
Employees
4
Memberships
4
Reporting
3
Total
12
Expected Entity Updates
Collection
Count
Employees
2
Reporting
1
Total
3
Expected Entity Deletes
Collection
Count
Reporting
1
Membership
1
Total
2
Something fishy is going on here. There should be a total of only 17 events while we're getting 27 (your number may vary or even be exactly 17 - we will see why)! Let us run a grouping by collection to figure out where our tally goes out of sync.
Counts by Collection
We split event counts by collection by using the parameters given below:
Param
Value
countsOnly
true
groupBy
collection
path
/
We get the following result:
Hmm, the departments collection has 3 events instead of the single create event that we would expect. Let's take a closer look.
Events for Collection
Departments
We fetch all events for the departments collection by using the parameters shown below:
Param
Value
path
/c/departments
sort
asc
We get the following result:
Now we have an answer! The first two events were a created, followed by a deleted of the same node (departments/44787328, see the meta.id field). Someone created a department node, and for some reason subsequently deleted it. However RecallGraph remembers everything, and we will see how we can get a peek into the contents of this deleted node (and possibly a motive behind deleting it) when we explore the SHOW endpoint. For now, we know part of the answer to the discrepancy in the total count.
We finish the exercise by similarly accessing the individual events for the reporting and the employees collections respectively (memberships counts already match up).
Reporting
Counts by Node
We fetch event counts grouped by node for the reporting collection by using the parameters shown below:
Param
Value
path
/c/reporting
groupBy
node
countsOnly
true
We get the following result:
The two nodes with 1 event each seem to be in order, most likely representing the reporting relations between Kyle --> Eric and Stan --> Eric. We know that Kenny's reporting relationship had to undergo one modification, followed by a deletion. Including the initial creation, that should be a total of 3 events, but here we see 5. The next step is to drill down into this.
Post-Filtered Events
The ideal way to fetch events when node ids are known is to use the node brace scope, but since this is a small dataset, we can get away with using the collection scope with a post-filter, just to give an example of post-filter usage. We use request parameters as shown below:
Param
Value
path
/c/reporting
groupBy
node
groupSort
asc
postFilter
node === "reporting/44799849"
We get the following result:
Note that events within a group are sorted in descending order in ctime by default, but we have reversed this order by using the groupSort parameter, so that now, the created event is listed at the top.
As expected, we start with a created event and end with a deleted event. However, instead of 1 updated event, we have 3! What could have been modified in those extra 2 updates? We will find out when we explore the DIFF endpoint.
Executing LOG with the following parameters would yield the same result:
No post-filter is needed in this case, as the pre-filter (in the scope defined by the path parameter) is restricting the node list to identical effect. Can you guess which method is generally faster?
Finally, we dig into events related to the employees collection.
Employees
Counts by Node
We fetch event counts grouped by node for the employees collection by using the parameters shown below:
Param
Value
path
/c/employees
groupBy
node
countsOnly
true
We get the following result:
There are 7 employee records instead of the expected 4! We know the ids of the 4 employees we have been working with. Let us drill down into the events related to the remaining 3 mysterious employees. We will again use a post-filter to filter out nodes that are already known to us.
Post-Filtered Events
We use request parameters as shown below:
Param
Value
path
/c/employees
groupBy
node
groupSort
asc
postFilter
!(node =* "employees/{44794449,44794453,44794457,44799683}" )
We get the following result:
We now see that someone created 3 employee nodes, and for some reason subsequently deleted them. We will see how we can get a peek into the contents of these deleted nodes (and possibly a motive behind deleting them) when we explore the SHOW endpoint.
We could also use the following parameters to get exactly the same results:
No post-filter is needed in this case, as the pre-filter (in the scope defined by the path parameter) is restricting the node list to identical effect. Can you guess which method is generally faster?
Last updated