Skip to content

Commit b75ea56

Browse files
sanityclaude
andauthored
refactor(logging): apply structured logging best practices across codebase (#2267)
Co-authored-by: Claude <[email protected]>
1 parent 56177ab commit b75ea56

File tree

28 files changed

+1962
-763
lines changed

28 files changed

+1962
-763
lines changed

crates/core/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ name = "transport_perf"
115115
harness = false
116116
required-features = ["bench"]
117117

118+
[build-dependencies]
119+
chrono = "0.4"
120+
118121
[features]
119122
default = ["redb", "trace", "websocket"]
120123
sqlite = ["sqlx"]

crates/core/build.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::process::Command;
22

33
fn main() {
4+
// Emit build metadata for startup logging
5+
emit_build_metadata();
6+
47
// Skip flatbuffers generation for cross-compilation
58
if std::env::var("CARGO_BUILD_TARGET").is_ok() {
69
return;
@@ -19,3 +22,33 @@ fn main() {
1922
let _ = Command::new("cargo").arg("fmt").status();
2023
}
2124
}
25+
26+
fn emit_build_metadata() {
27+
// Git commit hash
28+
let git_hash = Command::new("git")
29+
.args(["rev-parse", "--short=12", "HEAD"])
30+
.output()
31+
.ok()
32+
.and_then(|o| String::from_utf8(o.stdout).ok())
33+
.map(|s| s.trim().to_string())
34+
.unwrap_or_else(|| "unknown".to_string());
35+
println!("cargo:rustc-env=GIT_COMMIT_HASH={git_hash}");
36+
37+
// Git dirty flag
38+
let git_dirty = Command::new("git")
39+
.args(["status", "--porcelain"])
40+
.output()
41+
.ok()
42+
.map(|o| !o.stdout.is_empty())
43+
.unwrap_or(false);
44+
let dirty_suffix = if git_dirty { "-dirty" } else { "" };
45+
println!("cargo:rustc-env=GIT_DIRTY={dirty_suffix}");
46+
47+
// Build timestamp (ISO 8601)
48+
let timestamp = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%SZ").to_string();
49+
println!("cargo:rustc-env=BUILD_TIMESTAMP={timestamp}");
50+
51+
// Rebuild if git HEAD changes
52+
println!("cargo:rerun-if-changed=.git/HEAD");
53+
println!("cargo:rerun-if-changed=.git/index");
54+
}

crates/core/src/bin/freenet.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,23 @@ use freenet::{
88
};
99
use std::sync::Arc;
1010

11+
/// Build metadata embedded at compile time
12+
mod build_info {
13+
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
14+
pub const GIT_COMMIT: &str = env!("GIT_COMMIT_HASH");
15+
pub const GIT_DIRTY: &str = env!("GIT_DIRTY");
16+
pub const BUILD_TIMESTAMP: &str = env!("BUILD_TIMESTAMP");
17+
}
18+
1119
async fn run(config: Config) -> anyhow::Result<()> {
20+
// Log build info on startup - critical for correlating logs with code version
21+
tracing::info!(
22+
version = build_info::VERSION,
23+
git_commit = %format!("{}{}", build_info::GIT_COMMIT, build_info::GIT_DIRTY),
24+
build_timestamp = build_info::BUILD_TIMESTAMP,
25+
"Freenet node starting"
26+
);
27+
1228
match config.mode {
1329
OperationMode::Local => run_local(config).await,
1430
OperationMode::Network => run_network(config).await,

crates/core/src/client_events/mod.rs

Lines changed: 485 additions & 129 deletions
Large diffs are not rendered by default.

crates/core/src/client_events/websocket.rs

Lines changed: 95 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,10 @@ impl WebSocketProxy {
118118
.with_token(auth_token)
119119
.with_attested_contract(attested_contract)
120120
} else {
121-
tracing::warn!("client: {client_id} not found");
121+
tracing::warn!(
122+
client_id = %client_id,
123+
"Client not found for request"
124+
);
122125
return Err(ErrorKind::UnknownClient(client_id.into()).into());
123126
}
124127
}
@@ -142,7 +145,10 @@ impl WebSocketProxy {
142145
.with_token(auth_token)
143146
.with_attested_contract(attested_contract)
144147
} else {
145-
tracing::warn!("client: {client_id} not found");
148+
tracing::warn!(
149+
client_id = %client_id,
150+
"Client not found for request"
151+
);
146152
return Err(ErrorKind::UnknownClient(client_id.into()).into());
147153
}
148154
}
@@ -166,7 +172,10 @@ impl WebSocketProxy {
166172
.with_token(auth_token)
167173
.with_attested_contract(attested_contract)
168174
} else {
169-
tracing::warn!("client: {client_id} not found");
175+
tracing::warn!(
176+
client_id = %client_id,
177+
"Client not found for request"
178+
);
170179
return Err(ErrorKind::UnknownClient(client_id.into()).into());
171180
}
172181
}
@@ -559,10 +568,11 @@ async fn process_host_response(
559568
summary,
560569
}) => {
561570
tracing::debug!(
562-
"Processing UpdateResponse for WebSocket delivery - client: {}, key: {}, summary length: {}",
563-
id,
564-
key,
565-
summary.size()
571+
client_id = %id,
572+
contract = %key,
573+
summary_size = summary.size(),
574+
phase = "update_response",
575+
"Processing UpdateResponse for WebSocket delivery"
566576
);
567577
}
568578
_ => {
@@ -596,9 +606,10 @@ async fn process_host_response(
596606
..
597607
})) => {
598608
tracing::debug!(
599-
"About to serialize UpdateResponse for WebSocket delivery - client: {}, key: {}",
600-
client_id,
601-
key
609+
client_id = %client_id,
610+
contract = %key,
611+
phase = "serializing",
612+
"Serializing UpdateResponse for WebSocket delivery"
602613
);
603614
Some(*key)
604615
}
@@ -616,10 +627,11 @@ async fn process_host_response(
616627
// Log serialization completion for UPDATE responses
617628
if let Some(key) = is_update_response {
618629
tracing::debug!(
619-
"Serialized UpdateResponse for WebSocket delivery - client: {}, key: {}, size: {} bytes",
620-
client_id,
621-
key,
622-
serialized_res.len()
630+
client_id = %client_id,
631+
contract = %key,
632+
size_bytes = serialized_res.len(),
633+
phase = "serialized",
634+
"Serialized UpdateResponse for WebSocket delivery"
623635
);
624636
}
625637

@@ -630,17 +642,19 @@ async fn process_host_response(
630642
match &send_result {
631643
Ok(()) => {
632644
tracing::debug!(
633-
"Successfully sent UpdateResponse over WebSocket to client {} for key {}",
634-
client_id,
635-
key
645+
client_id = %client_id,
646+
contract = %key,
647+
phase = "sent",
648+
"Successfully sent UpdateResponse over WebSocket"
636649
);
637650
}
638651
Err(err) => {
639652
tracing::error!(
640-
"Failed to send UpdateResponse over WebSocket to client {} for key {}: {:?}",
641-
client_id,
642-
key,
643-
err
653+
client_id = %client_id,
654+
contract = %key,
655+
error = ?err,
656+
phase = "error",
657+
"Failed to send UpdateResponse over WebSocket"
644658
);
645659
}
646660
}
@@ -663,9 +677,13 @@ async fn process_host_response(
663677
))?;
664678
tx.send(Message::Binary(result_error.into())).await?;
665679
tx.send(Message::Close(None)).await?;
666-
tracing::warn!("node shut down while handling responses for {client_id}");
680+
tracing::warn!(
681+
client_id = %client_id,
682+
"Node shut down while handling responses"
683+
);
667684
Err(anyhow::anyhow!(
668-
"node shut down while handling responses for {client_id}"
685+
"node shut down while handling responses for client {}",
686+
client_id
669687
))
670688
}
671689
}
@@ -696,36 +714,53 @@ impl ClientEventsProxy for WebSocketProxy {
696714
async move {
697715
// Log UPDATE responses specifically
698716
match &result {
699-
Ok(HostResponse::ContractResponse(freenet_stdlib::client_api::ContractResponse::UpdateResponse { key, summary })) => {
717+
Ok(HostResponse::ContractResponse(
718+
freenet_stdlib::client_api::ContractResponse::UpdateResponse { key, summary },
719+
)) => {
700720
tracing::debug!(
701-
"WebSocket send() called with UpdateResponse for client {} - key: {}, summary length: {}",
702-
id,
703-
key,
704-
summary.size()
721+
client_id = %id,
722+
contract = %key,
723+
summary_size = summary.size(),
724+
"WebSocket send() called with UpdateResponse"
705725
);
706726
}
707727
Ok(other_response) => {
708-
tracing::debug!("WebSocket send() called with response for client {}: {:?}", id, other_response);
728+
tracing::debug!(
729+
client_id = %id,
730+
response = ?other_response,
731+
"WebSocket send() called with response"
732+
);
709733
}
710734
Err(error) => {
711-
tracing::debug!("WebSocket send() called with error for client {}: {:?}", id, error);
735+
tracing::debug!(
736+
client_id = %id,
737+
error = ?error,
738+
"WebSocket send() called with error"
739+
);
712740
}
713741
}
714742

715743
if let Some(ch) = self.response_channels.remove(&id) {
716744
// Log success/failure of sending UPDATE responses
717-
if let Ok(HostResponse::ContractResponse(freenet_stdlib::client_api::ContractResponse::UpdateResponse { key, .. })) = &result {
745+
if let Ok(HostResponse::ContractResponse(
746+
freenet_stdlib::client_api::ContractResponse::UpdateResponse { key, .. },
747+
)) = &result
748+
{
718749
tracing::debug!(
719-
"Found WebSocket channel for client {}, sending UpdateResponse for key {}",
720-
id,
721-
key
750+
client_id = %id,
751+
contract = %key,
752+
"Found WebSocket channel, sending UpdateResponse"
722753
);
723754
}
724755

725756
// Check if this is an UPDATE response and extract key before moving result
726757
let update_key = match &result {
727-
Ok(HostResponse::ContractResponse(freenet_stdlib::client_api::ContractResponse::UpdateResponse { key, .. })) => Some(*key),
728-
_ => None
758+
Ok(HostResponse::ContractResponse(
759+
freenet_stdlib::client_api::ContractResponse::UpdateResponse {
760+
key, ..
761+
},
762+
)) => Some(*key),
763+
_ => None,
729764
};
730765

731766
let should_rm = result
@@ -741,16 +776,18 @@ impl ClientEventsProxy for WebSocketProxy {
741776
match send_result.is_ok() {
742777
true => {
743778
tracing::debug!(
744-
"Successfully sent UpdateResponse to client {} for key {}",
745-
id,
746-
key
779+
client_id = %id,
780+
contract = %key,
781+
phase = "sent",
782+
"Successfully sent UpdateResponse to client"
747783
);
748784
}
749785
false => {
750786
tracing::error!(
751-
"Failed to send UpdateResponse to client {} for key {} - channel send failed",
752-
id,
753-
key
787+
client_id = %id,
788+
contract = %key,
789+
phase = "error",
790+
"Failed to send UpdateResponse - channel send failed"
754791
);
755792
}
756793
}
@@ -760,20 +797,30 @@ impl ClientEventsProxy for WebSocketProxy {
760797
// still alive connection, keep it
761798
self.response_channels.insert(id, ch);
762799
} else {
763-
tracing::info!("dropped connection to client #{id}");
800+
tracing::info!(
801+
client_id = %id,
802+
"Dropped connection to client"
803+
);
764804
}
765805
} else {
766806
// Log when client is not found for UPDATE responses
767807
match &result {
768-
Ok(HostResponse::ContractResponse(freenet_stdlib::client_api::ContractResponse::UpdateResponse { key, .. })) => {
808+
Ok(HostResponse::ContractResponse(
809+
freenet_stdlib::client_api::ContractResponse::UpdateResponse {
810+
key, ..
811+
},
812+
)) => {
769813
tracing::error!(
770-
"Client {} not found in WebSocket response channels when trying to send UpdateResponse for key {}",
771-
id,
772-
key
814+
client_id = %id,
815+
contract = %key,
816+
"Client not found in WebSocket response channels for UpdateResponse"
773817
);
774818
}
775819
_ => {
776-
tracing::warn!("client: {id} not found");
820+
tracing::warn!(
821+
client_id = %id,
822+
"Client not found in response channels"
823+
);
777824
}
778825
}
779826
}

0 commit comments

Comments
 (0)