Skip to content

feat: implement activity log tracking for node tip changes and reachability#115

Open
Miracle656 wants to merge 1 commit into0xB10C:mainfrom
Miracle656:feature/activity-log-issue-27
Open

feat: implement activity log tracking for node tip changes and reachability#115
Miracle656 wants to merge 1 commit into0xB10C:mainfrom
Miracle656:feature/activity-log-issue-27

Conversation

@Miracle656
Copy link

Description

This PR implements the backend infrastructure for a per-node Activity Log to track chain tip changes and node reachability, addressing #27.

The implementation focuses on persisting historical events to the SQLite database and exposing them via a REST endpoint, laying the groundwork for future frontend visualization.

Architecture Updates

  1. Database Schema (src/db.rs):
    • Created a new activity_log table to store timestamped interactions.
    • Designed to track activity_type integers representing Node Tips Changed (0), Node Reachable (1), and Node Unreachable (2).
    • Stores stringified activity_data (like the JSON dump of the new ChainTip array or error messages) for later UI playback.
  2. Event Hooking (src/main.rs):
    • Intercepted existing logic inside the primary block-polling tokio loop to trigger new db::log_activity writes whenever !is_node_reachable() or last_tips != tips evaluates to true.
  3. Configuration Toggle (src/config.rs):
    • Honoring the request to keep the log granular to avoid DB bloat on testnets.
    • Introduced a new activity_log_enabled boolean flag which can be configured via config.toml on either a per-network or per-node basis.
  4. API Endpoint (src/api.rs):
    • Added a new warp REST route: GET /api/{network}/activity.json, which surfaces the last 100 timestamped events structured dynamically for UI consumption.

Testing

  • cargo check and cargo test pass successfully with the implemented Serialize bindings for the ChainTip and ChainTipStatus structs.
  • Verified the SQLite transactions and endpoint routing.

Note to Maintainers

As discussed in #27, building the actual visual replay components in the frontend UI might be better suited for a follow-up PR to keep this implementation focused. Please review the backend structures here, and I'd be happy to iterate on the specific SQL schemas or frontend consumption if requested!

Closes #27

@0xB10C
Copy link
Owner

0xB10C commented Mar 5, 2026

Can you squash these two commits into one? Thank you!

I'll have a closer look soon.

@Miracle656 Miracle656 force-pushed the feature/activity-log-issue-27 branch from d007f33 to 1484e87 Compare March 6, 2026 09:41
@Miracle656
Copy link
Author

Can you squash these two commits into one? Thank you!

I'll have a closer look soon.

duly noted and done

@Miracle656 Miracle656 force-pushed the feature/activity-log-issue-27 branch from 1484e87 to f264ee8 Compare March 9, 2026 11:31
src/db.rs Outdated
db: Db,
network: u32,
node_id: u32,
activity_type: u32,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be some kind of enum on the rust side. You can still store it as int in the db.

src/main.rs Outdated
db_write.clone(),
network.id,
node.info().id,
1,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a constant or enum. Not clear what 1 means.

src/main.rs Outdated
network.id,
node.info().id,
1,
"".to_string(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why empty string?

error.txt Outdated
Comment on lines +1 to +16
Checking fork-observer v0.1.0 (C:\Users\HP\Documents\boss\boss-portfolio-projects\fork-observer)
error[E0765]: unterminated double quote string
--> src\db.rs:191:57
|
191 | "done loading headers for network {}: headers={}",
| _________________________________________________________^
192 | | network,
193 | | headers.len()
194 | | );
... |
239 | | Ok(activities)
240 | | }
| |__^

For more information about this error, try `rustc --explain E0765`.
error: could not compile `fork-observer` (bin "fork-observer") due to 1 previous error
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated?

error2.txt Outdated
Comment on lines +1 to +38
Checking fork-observer v0.1.0 (C:\Users\HP\Documents\boss\boss-portfolio-projects\fork-observer)
error[E0277]: the trait bound `ChainTip: serde::Serialize` is not satisfied
--> src\main.rs:314:62
|
314 | ... let data = serde_json::to_string(&tips).unwrap_or_default();
| --------------------- ^^^^^ unsatisfied trait bound
| |
| required by a bound introduced by this call
|
help: the trait `Serialize` is not implemented for `ChainTip`
--> src\types.rs:273:1
|
273 | pub struct ChainTip {
| ^^^^^^^^^^^^^^^^^^^
= note: for local types consider adding `#[derive(serde::Serialize)]` to your `ChainTip` type
= note: for types from other crates check whether the crate offers a `serde` feature flag
= help: the following other types implement trait `Serialize`:
&'a T
&'a mut T
()
(T,)
(T0, T1)
(T0, T1, T2)
(T0, T1, T2, T3)
(T0, T1, T2, T3, T4)
and 372 others
= note: required for `Vec<ChainTip>` to implement `Serialize`
note: required by a bound in `serde_json::to_string`
--> C:\Users\HP\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\serde_json-1.0.145\src\ser.rs:2247:17
|
2245 | pub fn to_string<T>(value: &T) -> Result<String>
| --------- required by a bound in this function
2246 | where
2247 | T: ?Sized + Serialize,
| ^^^^^^^^^ required by this bound in `to_string`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `fork-observer` (bin "fork-observer") due to 1 previous error
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated?

error3.txt Outdated
Comment on lines +1 to +26
Checking fork-observer v0.1.0 (C:\Users\HP\Documents\boss\boss-portfolio-projects\fork-observer)
error[E0382]: borrow of moved value: `db_write`
--> src\main.rs:315:65
|
279 | let db_write = db_write.clone();
| -------- ---------------- this reinitialization might get skipped
| |
| move occurs because `db_write` has type `Arc<tokio::sync::Mutex<rusqlite::Connection>>`, which does not implement the `Copy` trait
...
287 | match db::write_to_db(&new_headers, db_write, network.id).await {
| -------- value moved here
...
315 | if let Err(db_e) = db::log_activity(db_write.clone(), network.id, node.info().id, 0, data).await {
| ^^^^^^^^ value borrowed here after move
|
note: consider changing this parameter type in function `write_to_db` to borrow instead if owning the value isn't necessary
--> src\db.rs:83:9
|
81 | pub async fn write_to_db(
| ----------- in this function
82 | new_headers: &Vec<HeaderInfo>,
83 | db: Db,
| ^^ this parameter takes ownership of the value

For more information about this error, try `rustc --explain E0382`.
error: could not compile `fork-observer` (bin "fork-observer") due to 1 previous error
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad once again

error_test.txt Outdated
Comment on lines +1 to +9
Compiling fork-observer v0.1.0 (C:\Users\HP\Documents\boss\boss-portfolio-projects\fork-observer)
error[E0063]: missing field `activity_log_enabled` in initializer of `node::NodeInfo`
--> src\main.rs:899:20
|
899 | let node = NodeInfo {
| ^^^^^^^^ missing `activity_log_enabled`

For more information about this error, try `rustc --explain E0063`.
error: could not compile `fork-observer` (bin "fork-observer" test) due to 1 previous error
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the error.txt files are unrelated, i pasted the error i got from the terminal to the txt file cause it was truncated and for more readability, i'll take everything out

@0xB10C
Copy link
Owner

0xB10C commented Mar 9, 2026

I think it would be better to have a SQL table per activity (tip changed, reachable, ..) with specific rows needed for that activity and reference it from the activity_log table. I think that gives us a bit more room for future use-cases instead of having only a String in there.

@0xB10C
Copy link
Owner

0xB10C commented Mar 9, 2026

Also note that you put "Test User" as your name in the git commit.

@Miracle656
Copy link
Author

I think it would be better to have a SQL table per activity (tip changed, reachable, ..) with specific rows needed for that activity and reference it from the activity_log table. I think that gives us a bit more room for future use-cases instead of having only a String in there.

from an architectural standpoint you are right, When initially designing the activity log, I chose to store the activity_data as a generic JSON TEXT blob inside a single table just a common pattern for fast prototyping, as a single table is very easy to query and doesn't require complex SQL queries. i'll start working on updating it to your suggestion

@Miracle656 Miracle656 force-pushed the feature/activity-log-issue-27 branch from f264ee8 to 69ee0e9 Compare March 9, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Activity log: Keep track of tip changes, nodes not being reachable, ...

2 participants