Skip to content

Commit b8c05c7

Browse files
authored
Merge pull request #4 from brytelands/solana_2_support
Solana 2 support
2 parents affe3cb + 53fbd6e commit b8c05c7

File tree

12 files changed

+570
-106
lines changed

12 files changed

+570
-106
lines changed

Dockerfile-logstash

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
################################################################################
88
# Create a stage for building the application.
99

10-
ARG RUST_VERSION=1.77.0
10+
ARG RUST_VERSION=1.81.0
1111
ARG APP_NAME=sologger
1212
FROM rust:${RUST_VERSION}-slim-bookworm AS build
1313
ARG APP_NAME
@@ -26,7 +26,8 @@ RUN --mount=type=bind,source=sologger-log-context,target=sologger-log-context \
2626
--mount=type=bind,source=sologger,target=sologger \
2727
--mount=type=bind,source=Cargo.toml,target=Cargo.toml \
2828
--mount=type=bind,source=Cargo.lock,target=Cargo.lock \
29-
--mount=type=bind,source=config/docker,target=config/docker \
29+
--mount=type=bind,source=config/docker/,target=config \
30+
--mount=type=bind,source=config,target=config \
3031
--mount=type=cache,target=/app/target/ \
3132
--mount=type=cache,target=/usr/local/cargo/registry/ \
3233
<<EOF

Dockerfile-otel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
################################################################################
88
# Create a stage for building the application.
99

10-
ARG RUST_VERSION=1.77.0
10+
ARG RUST_VERSION=1.81.0
1111
ARG APP_NAME=sologger
1212
FROM rust:${RUST_VERSION}-slim-bookworm AS build
1313
ARG APP_NAME

sologger-log-context/Cargo.toml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sologger_log_context"
3-
version = "0.1.2"
3+
version = "0.2.0"
44
edition = "2021"
55
authors = ["Will Kennedy"]
66
description = "Provides functionality to turn raw logs output by Solana RPCs into structured logs for specified program IDs"
@@ -15,10 +15,17 @@ exclude=["/tests", "/examples", "/benches", "/docs", "/target", "/.github", "/.g
1515
doctest = false
1616

1717
[dependencies]
18-
log = "0.4.21"
19-
regex = { version = "1.10.4" }
20-
serde = { version = "1.0.197", features = ["serde_derive", "derive"]}
21-
serde_json = {version = "1.0.115"}
22-
serde_derive = "1.0.197"
23-
bs58 = "0.5.0"
24-
lazy_static = "1.4.0"
18+
log = "0.4.22"
19+
regex = { version = "1.11.0" }
20+
serde = { version = "1.0.210", features = ["serde_derive", "derive"]}
21+
serde_json = {version = "1.0.128"}
22+
serde_derive = "1.0.210"
23+
bs58 = "0.5.1"
24+
lazy_static = "1.5.0"
25+
26+
[dev-dependencies]
27+
criterion = "0.5.1"
28+
29+
[[bench]]
30+
name = "log_context_benchmarks"
31+
harness = false
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use sologger_log_context::programs_selector::ProgramsSelector;
3+
use sologger_log_context::sologger_log_context::LogContext;
4+
5+
fn generate_sample_logs(n: usize) -> Vec<String> {
6+
let mut logs = Vec::with_capacity(n);
7+
for i in 0..n {
8+
logs.push("Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 invoke [1]".to_string());
9+
logs.push("Program log: Instruction: Initialize".to_string());
10+
logs.push("Program 11111111111111111111111111111111 invoke [2]".to_string());
11+
logs.push("Program 11111111111111111111111111111111 success".to_string());
12+
logs.push("Program log: Initialized new event. Current value".to_string());
13+
logs.push("Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 consumed 59783 of 200000 compute units".to_string());
14+
logs.push("Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 success".to_string());
15+
logs.push("Program AbcdefGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]".to_string());
16+
logs.push("Program log: Create".to_string());
17+
logs.push("Program AbcdefGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 5475 of 200000 compute units".to_string());
18+
logs.push("Program failed to complete: Invoked an instruction with data that is too large (12178014311288245306 > 10240)".to_string());
19+
logs.push("Program AbcdefGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL failed: Program failed to complete".to_string());
20+
}
21+
logs
22+
}
23+
24+
fn bench_parse_logs(c: &mut Criterion) {
25+
let logs = generate_sample_logs(100);
26+
let programs_selector = ProgramsSelector::new(&["*".to_string()]);
27+
28+
c.bench_function("parse_logs 100 entries", |b| {
29+
b.iter(|| {
30+
LogContext::parse_logs(
31+
black_box(&logs),
32+
black_box("".to_string()),
33+
black_box(&programs_selector),
34+
black_box(1),
35+
black_box("12345".to_string()),
36+
)
37+
})
38+
});
39+
}
40+
41+
fn bench_get_invoke_program_id(c: &mut Criterion) {
42+
let log = "Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 invoke [1]".to_string();
43+
44+
c.bench_function("get_invoke_program_id", |b| {
45+
b.iter(|| LogContext::get_invoke_program_id(black_box(&log)))
46+
});
47+
}
48+
49+
fn bench_get_program_data(c: &mut Criterion) {
50+
let log = "Program data: f8oPt8jABAy1K0GKz0oSSO8oves0qt09GsKz1QNA3hkOpcvC0rPMywt4KffaIJMAVQlyjQhUVOXGyn09Lxu29Ty1k5m72ijBAAAAAAAAAAAAuZINBxwAAAC7AAAAAAAAAIjnFQEAAAAA".to_string();
51+
52+
c.bench_function("get_program_data", |b| {
53+
b.iter(|| LogContext::get_program_data(black_box(&log)))
54+
});
55+
}
56+
57+
fn bench_to_json(c: &mut Criterion) {
58+
let log_context = LogContext::new(
59+
"9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7".to_string(),
60+
1,
61+
"unique_id".to_string(),
62+
0,
63+
1,
64+
"signature".to_string(),
65+
);
66+
67+
c.bench_function("to_json", |b| {
68+
b.iter(|| black_box(&log_context).to_json())
69+
});
70+
}
71+
72+
criterion_group!(
73+
benches,
74+
bench_parse_logs,
75+
bench_get_invoke_program_id,
76+
bench_get_program_data,
77+
bench_to_json
78+
);
79+
criterion_main!(benches);

sologger-log-context/src/sologger_log_context.rs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,4 +1149,165 @@ mod tests {
11491149

11501150
let log_contexts = LogContext::parse_logs(&raw_logs, "".to_string(), &programs_selector,216778028, "KDhFgTogstghe9P1jVjVepnwfR9ZbcU8a6D21jXBh3PPyfkkd92MmevsWW7qb6QtfmfmWxAPYnL3xZR81xVCmeQ".to_string());
11511151
}
1152+
1153+
1154+
#[test]
1155+
fn log_parser_empty_logs_test() {
1156+
let logs: Vec<String> = vec![];
1157+
let programs_selector = ProgramsSelector::new_all_programs();
1158+
1159+
let log_contexts = LogContext::parse_logs(
1160+
&logs,
1161+
"".to_string(),
1162+
&programs_selector,
1163+
1,
1164+
"12345".to_string(),
1165+
);
1166+
1167+
assert!(log_contexts.is_empty());
1168+
}
1169+
1170+
#[test]
1171+
fn log_parser_nested_invocations_test() {
1172+
let logs: Vec<String> = vec![
1173+
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
1174+
"Program B222222222222222222222222222222222222222 invoke [2]".to_string(),
1175+
"Program C333333333333333333333333333333333333333 invoke [3]".to_string(),
1176+
"Program C333333333333333333333333333333333333333 success".to_string(),
1177+
"Program B222222222222222222222222222222222222222 success".to_string(),
1178+
"Program A111111111111111111111111111111111111111 success".to_string(),
1179+
];
1180+
let programs_selector = ProgramsSelector::new_all_programs();
1181+
1182+
let log_contexts = LogContext::parse_logs(
1183+
&logs,
1184+
"".to_string(),
1185+
&programs_selector,
1186+
1,
1187+
"12345".to_string(),
1188+
);
1189+
1190+
assert_eq!(log_contexts.len(), 3);
1191+
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
1192+
assert_eq!(log_contexts[1].program_id, "B222222222222222222222222222222222222222");
1193+
assert_eq!(log_contexts[2].program_id, "C333333333333333333333333333333333333333");
1194+
assert_eq!(log_contexts[0].depth, 1);
1195+
assert_eq!(log_contexts[1].depth, 2);
1196+
assert_eq!(log_contexts[2].depth, 3);
1197+
}
1198+
1199+
#[test]
1200+
fn log_parser_mismatched_invoke_success_test() {
1201+
let logs: Vec<String> = vec![
1202+
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
1203+
"Program B222222222222222222222222222222222222222 invoke [2]".to_string(),
1204+
"Program A111111111111111111111111111111111111111 success".to_string(),
1205+
];
1206+
let programs_selector = ProgramsSelector::new_all_programs();
1207+
1208+
let log_contexts = LogContext::parse_logs(
1209+
&logs,
1210+
"".to_string(),
1211+
&programs_selector,
1212+
1,
1213+
"12345".to_string(),
1214+
);
1215+
1216+
assert_eq!(log_contexts.len(), 2);
1217+
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
1218+
assert_eq!(log_contexts[1].program_id, "B222222222222222222222222222222222222222");
1219+
}
1220+
1221+
#[test]
1222+
fn log_parser_program_return_test() {
1223+
let logs: Vec<String> = vec![
1224+
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
1225+
"Program return: A111111111111111111111111111111111111111 SomeReturnValue".to_string(),
1226+
"Program A111111111111111111111111111111111111111 success".to_string(),
1227+
];
1228+
let programs_selector = ProgramsSelector::new_all_programs();
1229+
1230+
let log_contexts = LogContext::parse_logs(
1231+
&logs,
1232+
"".to_string(),
1233+
&programs_selector,
1234+
1,
1235+
"12345".to_string(),
1236+
);
1237+
1238+
assert_eq!(log_contexts.len(), 1);
1239+
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
1240+
assert_eq!(log_contexts[0].invoke_result, "SomeReturnValue");
1241+
}
1242+
1243+
#[test]
1244+
fn log_parser_program_consumption_test() {
1245+
let logs: Vec<String> = vec![
1246+
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
1247+
"Program consumption: 50000".to_string(),
1248+
"Program A111111111111111111111111111111111111111 success".to_string(),
1249+
];
1250+
let programs_selector = ProgramsSelector::new_all_programs();
1251+
1252+
let log_contexts = LogContext::parse_logs(
1253+
&logs,
1254+
"".to_string(),
1255+
&programs_selector,
1256+
1,
1257+
"12345".to_string(),
1258+
);
1259+
1260+
assert_eq!(log_contexts.len(), 1);
1261+
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
1262+
assert_eq!(log_contexts[0].raw_logs.len(), 3);
1263+
assert!(log_contexts[0].raw_logs.contains(&"Program consumption: 50000".to_string()));
1264+
}
1265+
1266+
#[test]
1267+
fn log_parser_multiple_instructions_test() {
1268+
let logs: Vec<String> = vec![
1269+
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
1270+
"Program A111111111111111111111111111111111111111 success".to_string(),
1271+
"Program B222222222222222222222222222222222222222 invoke [1]".to_string(),
1272+
"Program B222222222222222222222222222222222222222 success".to_string(),
1273+
];
1274+
let programs_selector = ProgramsSelector::new_all_programs();
1275+
1276+
let log_contexts = LogContext::parse_logs(
1277+
&logs,
1278+
"".to_string(),
1279+
&programs_selector,
1280+
1,
1281+
"12345".to_string(),
1282+
);
1283+
1284+
assert_eq!(log_contexts.len(), 2);
1285+
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
1286+
assert_eq!(log_contexts[1].program_id, "B222222222222222222222222222222222222222");
1287+
assert_eq!(log_contexts[0].instruction_index, 0);
1288+
assert_eq!(log_contexts[1].instruction_index, 1);
1289+
}
1290+
1291+
#[test]
1292+
fn log_parser_transaction_error_test() {
1293+
let logs: Vec<String> = vec![
1294+
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
1295+
"Program A111111111111111111111111111111111111111 failed: custom program error: 0x1".to_string(),
1296+
];
1297+
let programs_selector = ProgramsSelector::new_all_programs();
1298+
1299+
let log_contexts = LogContext::parse_logs(
1300+
&logs,
1301+
"Transaction failed".to_string(),
1302+
&programs_selector,
1303+
1,
1304+
"12345".to_string(),
1305+
);
1306+
1307+
assert_eq!(log_contexts.len(), 1);
1308+
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
1309+
assert_eq!(log_contexts[0].transaction_error, "Transaction failed");
1310+
assert_eq!(log_contexts[0].errors.len(), 1);
1311+
assert_eq!(log_contexts[0].errors[0], "custom program error: 0x1");
1312+
}
11521313
}
Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sologger_log_transformer"
3-
version = "0.1.4"
3+
version = "0.2.0"
44
edition = "2021"
55
authors = ["Will Kennedy"]
66
description = "Provides utility to extract logs from various Solana API structs, such as blocks, transactions and responses."
@@ -15,9 +15,16 @@ exclude=["/tests", "/examples", "/benches", "/docs", "/target", "/.github", "/.g
1515
doctest = false
1616

1717
[dependencies]
18-
anyhow = "1.0.81"
19-
solana-rpc-client = "1.18.12"
20-
solana-rpc-client-api = "1.18.12"
21-
solana-transaction-status = "1.18.12"
22-
solana-sdk = "1.18.12"
23-
sologger_log_context = "0.1.2"
18+
anyhow = "1.0.89"
19+
solana-rpc-client = "2.0.13"
20+
solana-rpc-client-api = "2.0.13"
21+
solana-transaction-status = "2.0.13"
22+
solana-sdk = "2.0.13"
23+
sologger_log_context = "0.2.0"
24+
25+
[dev-dependencies]
26+
criterion = "0.5.1"
27+
28+
[[bench]]
29+
name = "log_context_transformer_benchmarks"
30+
harness = false

0 commit comments

Comments
 (0)