Skip to content

Commit

Permalink
Merge pull request #4 from brytelands/solana_2_support
Browse files Browse the repository at this point in the history
Solana 2 support
  • Loading branch information
wkennedy authored Oct 13, 2024
2 parents affe3cb + 53fbd6e commit b8c05c7
Show file tree
Hide file tree
Showing 12 changed files with 570 additions and 106 deletions.
5 changes: 3 additions & 2 deletions Dockerfile-logstash
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.77.0
ARG RUST_VERSION=1.81.0
ARG APP_NAME=sologger
FROM rust:${RUST_VERSION}-slim-bookworm AS build
ARG APP_NAME
Expand All @@ -26,7 +26,8 @@ RUN --mount=type=bind,source=sologger-log-context,target=sologger-log-context \
--mount=type=bind,source=sologger,target=sologger \
--mount=type=bind,source=Cargo.toml,target=Cargo.toml \
--mount=type=bind,source=Cargo.lock,target=Cargo.lock \
--mount=type=bind,source=config/docker,target=config/docker \
--mount=type=bind,source=config/docker/,target=config \
--mount=type=bind,source=config,target=config \
--mount=type=cache,target=/app/target/ \
--mount=type=cache,target=/usr/local/cargo/registry/ \
<<EOF
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile-otel
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
################################################################################
# Create a stage for building the application.

ARG RUST_VERSION=1.77.0
ARG RUST_VERSION=1.81.0
ARG APP_NAME=sologger
FROM rust:${RUST_VERSION}-slim-bookworm AS build
ARG APP_NAME
Expand Down
23 changes: 15 additions & 8 deletions sologger-log-context/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sologger_log_context"
version = "0.1.2"
version = "0.2.0"
edition = "2021"
authors = ["Will Kennedy"]
description = "Provides functionality to turn raw logs output by Solana RPCs into structured logs for specified program IDs"
Expand All @@ -15,10 +15,17 @@ exclude=["/tests", "/examples", "/benches", "/docs", "/target", "/.github", "/.g
doctest = false

[dependencies]
log = "0.4.21"
regex = { version = "1.10.4" }
serde = { version = "1.0.197", features = ["serde_derive", "derive"]}
serde_json = {version = "1.0.115"}
serde_derive = "1.0.197"
bs58 = "0.5.0"
lazy_static = "1.4.0"
log = "0.4.22"
regex = { version = "1.11.0" }
serde = { version = "1.0.210", features = ["serde_derive", "derive"]}
serde_json = {version = "1.0.128"}
serde_derive = "1.0.210"
bs58 = "0.5.1"
lazy_static = "1.5.0"

[dev-dependencies]
criterion = "0.5.1"

[[bench]]
name = "log_context_benchmarks"
harness = false
79 changes: 79 additions & 0 deletions sologger-log-context/benches/log_context_benchmarks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use sologger_log_context::programs_selector::ProgramsSelector;
use sologger_log_context::sologger_log_context::LogContext;

fn generate_sample_logs(n: usize) -> Vec<String> {
let mut logs = Vec::with_capacity(n);
for i in 0..n {
logs.push("Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 invoke [1]".to_string());
logs.push("Program log: Instruction: Initialize".to_string());
logs.push("Program 11111111111111111111111111111111 invoke [2]".to_string());
logs.push("Program 11111111111111111111111111111111 success".to_string());
logs.push("Program log: Initialized new event. Current value".to_string());
logs.push("Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 consumed 59783 of 200000 compute units".to_string());
logs.push("Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 success".to_string());
logs.push("Program AbcdefGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]".to_string());
logs.push("Program log: Create".to_string());
logs.push("Program AbcdefGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 5475 of 200000 compute units".to_string());
logs.push("Program failed to complete: Invoked an instruction with data that is too large (12178014311288245306 > 10240)".to_string());
logs.push("Program AbcdefGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL failed: Program failed to complete".to_string());
}
logs
}

fn bench_parse_logs(c: &mut Criterion) {
let logs = generate_sample_logs(100);
let programs_selector = ProgramsSelector::new(&["*".to_string()]);

c.bench_function("parse_logs 100 entries", |b| {
b.iter(|| {
LogContext::parse_logs(
black_box(&logs),
black_box("".to_string()),
black_box(&programs_selector),
black_box(1),
black_box("12345".to_string()),
)
})
});
}

fn bench_get_invoke_program_id(c: &mut Criterion) {
let log = "Program 9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7 invoke [1]".to_string();

c.bench_function("get_invoke_program_id", |b| {
b.iter(|| LogContext::get_invoke_program_id(black_box(&log)))
});
}

fn bench_get_program_data(c: &mut Criterion) {
let log = "Program data: f8oPt8jABAy1K0GKz0oSSO8oves0qt09GsKz1QNA3hkOpcvC0rPMywt4KffaIJMAVQlyjQhUVOXGyn09Lxu29Ty1k5m72ijBAAAAAAAAAAAAuZINBxwAAAC7AAAAAAAAAIjnFQEAAAAA".to_string();

c.bench_function("get_program_data", |b| {
b.iter(|| LogContext::get_program_data(black_box(&log)))
});
}

fn bench_to_json(c: &mut Criterion) {
let log_context = LogContext::new(
"9RX7oz3WN5VRTqekBBHBvEJFVMNRnrCmVy7S6B6S5oU7".to_string(),
1,
"unique_id".to_string(),
0,
1,
"signature".to_string(),
);

c.bench_function("to_json", |b| {
b.iter(|| black_box(&log_context).to_json())
});
}

criterion_group!(
benches,
bench_parse_logs,
bench_get_invoke_program_id,
bench_get_program_data,
bench_to_json
);
criterion_main!(benches);
161 changes: 161 additions & 0 deletions sologger-log-context/src/sologger_log_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1149,4 +1149,165 @@ mod tests {

let log_contexts = LogContext::parse_logs(&raw_logs, "".to_string(), &programs_selector,216778028, "KDhFgTogstghe9P1jVjVepnwfR9ZbcU8a6D21jXBh3PPyfkkd92MmevsWW7qb6QtfmfmWxAPYnL3xZR81xVCmeQ".to_string());
}


#[test]
fn log_parser_empty_logs_test() {
let logs: Vec<String> = vec![];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert!(log_contexts.is_empty());
}

#[test]
fn log_parser_nested_invocations_test() {
let logs: Vec<String> = vec![
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
"Program B222222222222222222222222222222222222222 invoke [2]".to_string(),
"Program C333333333333333333333333333333333333333 invoke [3]".to_string(),
"Program C333333333333333333333333333333333333333 success".to_string(),
"Program B222222222222222222222222222222222222222 success".to_string(),
"Program A111111111111111111111111111111111111111 success".to_string(),
];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert_eq!(log_contexts.len(), 3);
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
assert_eq!(log_contexts[1].program_id, "B222222222222222222222222222222222222222");
assert_eq!(log_contexts[2].program_id, "C333333333333333333333333333333333333333");
assert_eq!(log_contexts[0].depth, 1);
assert_eq!(log_contexts[1].depth, 2);
assert_eq!(log_contexts[2].depth, 3);
}

#[test]
fn log_parser_mismatched_invoke_success_test() {
let logs: Vec<String> = vec![
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
"Program B222222222222222222222222222222222222222 invoke [2]".to_string(),
"Program A111111111111111111111111111111111111111 success".to_string(),
];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert_eq!(log_contexts.len(), 2);
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
assert_eq!(log_contexts[1].program_id, "B222222222222222222222222222222222222222");
}

#[test]
fn log_parser_program_return_test() {
let logs: Vec<String> = vec![
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
"Program return: A111111111111111111111111111111111111111 SomeReturnValue".to_string(),
"Program A111111111111111111111111111111111111111 success".to_string(),
];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert_eq!(log_contexts.len(), 1);
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
assert_eq!(log_contexts[0].invoke_result, "SomeReturnValue");
}

#[test]
fn log_parser_program_consumption_test() {
let logs: Vec<String> = vec![
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
"Program consumption: 50000".to_string(),
"Program A111111111111111111111111111111111111111 success".to_string(),
];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert_eq!(log_contexts.len(), 1);
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
assert_eq!(log_contexts[0].raw_logs.len(), 3);
assert!(log_contexts[0].raw_logs.contains(&"Program consumption: 50000".to_string()));
}

#[test]
fn log_parser_multiple_instructions_test() {
let logs: Vec<String> = vec![
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
"Program A111111111111111111111111111111111111111 success".to_string(),
"Program B222222222222222222222222222222222222222 invoke [1]".to_string(),
"Program B222222222222222222222222222222222222222 success".to_string(),
];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert_eq!(log_contexts.len(), 2);
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
assert_eq!(log_contexts[1].program_id, "B222222222222222222222222222222222222222");
assert_eq!(log_contexts[0].instruction_index, 0);
assert_eq!(log_contexts[1].instruction_index, 1);
}

#[test]
fn log_parser_transaction_error_test() {
let logs: Vec<String> = vec![
"Program A111111111111111111111111111111111111111 invoke [1]".to_string(),
"Program A111111111111111111111111111111111111111 failed: custom program error: 0x1".to_string(),
];
let programs_selector = ProgramsSelector::new_all_programs();

let log_contexts = LogContext::parse_logs(
&logs,
"Transaction failed".to_string(),
&programs_selector,
1,
"12345".to_string(),
);

assert_eq!(log_contexts.len(), 1);
assert_eq!(log_contexts[0].program_id, "A111111111111111111111111111111111111111");
assert_eq!(log_contexts[0].transaction_error, "Transaction failed");
assert_eq!(log_contexts[0].errors.len(), 1);
assert_eq!(log_contexts[0].errors[0], "custom program error: 0x1");
}
}
21 changes: 14 additions & 7 deletions sologger-log-transformer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sologger_log_transformer"
version = "0.1.4"
version = "0.2.0"
edition = "2021"
authors = ["Will Kennedy"]
description = "Provides utility to extract logs from various Solana API structs, such as blocks, transactions and responses."
Expand All @@ -15,9 +15,16 @@ exclude=["/tests", "/examples", "/benches", "/docs", "/target", "/.github", "/.g
doctest = false

[dependencies]
anyhow = "1.0.81"
solana-rpc-client = "1.18.12"
solana-rpc-client-api = "1.18.12"
solana-transaction-status = "1.18.12"
solana-sdk = "1.18.12"
sologger_log_context = "0.1.2"
anyhow = "1.0.89"
solana-rpc-client = "2.0.13"
solana-rpc-client-api = "2.0.13"
solana-transaction-status = "2.0.13"
solana-sdk = "2.0.13"
sologger_log_context = "0.2.0"

[dev-dependencies]
criterion = "0.5.1"

[[bench]]
name = "log_context_transformer_benchmarks"
harness = false
Loading

0 comments on commit b8c05c7

Please sign in to comment.