# __ __ __
# \ \ / / / /
# \ V / / /
# \_/ \/
#
# V E C T O R
# Configuration
#
# ------------------------------------------------------------------------------
# Website: https://vector.dev
# Docs: https://vector.dev/docs
# Chat: https://chat.vector.dev
# ------------------------------------------------------------------------------
# Solana log source
[sources.solana_logs]
type = "file"
read_from = "beginning"
ignore_older_secs = 60
include = ["/home/sol/solana-rpc.log"]
# Parse Solana logs
[transforms.parse_solana_logs]
type = "remap"
drop_on_error = true
inputs = ["solana_logs"]
source = '''
.grok_results = parse_groks!(
.message,
patterns: [
"\\[%{_timestamp} %{_loglevel} %{_source}\\] %{_message}"
],
aliases: {
"_timestamp": "%{TIMESTAMP_ISO8601:timestamp}",
"_loglevel": "%{LOGLEVEL:level}",
"_message": "%{GREEDYDATA:message}",
"_source": "%{DATA:source}"
}
)
.dt = .grok_results.timestamp
.level = .grok_results.level
.source = strip_whitespace!(.grok_results.source)
.message = .grok_results.message
del(.grok_results)
'''
# Filter Solana logs for Clockwork logs
[transforms.filter_solana_logs]
inputs = ["parse_solana_logs"]
type = "filter"
condition = '''
.source == "clockwork_plugin::builders::thread_exec" ||
.source == "clockwork_plugin::executors::tx" ||
.source == "solana_validator" ||
.source == "solana_core::validator"
'''
# Parse program logs into JSON
[transforms.parse_clockwork_logs]
type = "remap"
inputs = ["filter_solana_logs"]
source = '''
if .source == "clockwork_plugin::builders::thread_exec" {
.grok_results = parse_groks!(
.message,
patterns: ["thread: %{_thread} simulation_error: %{_error} logs: %{_logs}"],
aliases: {
"_thread": "%{DATA:thread}",
"_error": "%{QUOTEDSTRING:error}",
"_logs": "%{GREEDYDATA:logs}"
}
)
.thread = .grok_results.thread
.error_msg = .grok_results.error
.program_logs = parse_json!(.grok_results.logs)
del(.grok_results)
}
'''
# Filter for only Clockwork simulation logs
[transforms.filter_clockwork_simulation_logs]
type = "filter"
inputs = ["parse_clockwork_logs"]
condition = '''
.source == "clockwork_plugin::builders::thread_exec" &&
!is_null(.error_msg)
'''
# Throttle Clockwork simulation logs
[transforms.throttle_clockwork_simulation_logs]
type = "throttle"
inputs = ["filter_clockwork_simulation_logs"]
key_field = "{{ thread }}"
threshold = 1
window_secs = 30
# Pipe to Logtail
[sinks.logtail]
type = "http"
uri = "https://in.logtail.com/"
encoding.codec = "json"
auth.strategy = "bearer"
auth.token = "YOUR_AUTH_KEY"
inputs = ["throttle_clockwork_simulation_logs"]
# Test Solana log parser
[[tests]]
name = "solana_metrics_test"
[[tests.inputs]]
insert_at = "parse_solana_logs"
type = "raw"
value = "[2023-01-10T17:21:42.218012551Z INFO solana_metrics::metrics] datapoint: pubsub_notifications created_to_queue_time_us=20i"
[[tests.outputs]]
extract_from = "parse_solana_logs"
[[tests.outputs.conditions]]
type = "vrl"
source = '''
assert_eq!(.dt, "2023-01-10T17:21:42.218012551Z")
assert_eq!(.level, "INFO")
assert_eq!(.source, "solana_metrics::metrics")
assert_eq!(.message, "datapoint: pubsub_notifications created_to_queue_time_us=20i")
'''
# Test Clockwork log parser
[[tests]]
name = "clockwork_simulation_test"
[[tests.inputs]]
insert_at = "parse_solana_logs"
type = "raw"
value = '[2023-01-11T04:37:09.059509973Z INFO clockwork_plugin::builders::thread_exec] thread: 9K4g3LYdwKhTJVQv85EvsAn7uHo5pSyq7qNs2FqrsD1K simulation_error: "Transaction results in an account (1) without insufficient funds for rent" logs: ["Program ComputeBudget111111111111111111111111111111 invoke [1]", "Program ComputeBudget111111111111111111111111111111 success", "Program 3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv invoke [1]", "Program log: Instruction: ThreadKickoff", "Program 3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv consumed 83495 of 1400000 compute units", "Program 3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv success"]'
[[tests.outputs]]
extract_from = "parse_clockwork_logs"
[[tests.outputs.conditions]]
type = "vrl"
source = '''
assert_eq!(.dt, "2023-01-11T04:37:09.059509973Z")
assert_eq!(.level, "INFO")
assert_eq!(.source, "clockwork_plugin::builders::thread_exec")
assert_eq!(.thread, "9K4g3LYdwKhTJVQv85EvsAn7uHo5pSyq7qNs2FqrsD1K")
assert_eq!(.error_msg, "\"Transaction results in an account (1) without insufficient funds for rent\"")
assert_eq!(.program_logs, ["Program ComputeBudget111111111111111111111111111111 invoke [1]", "Program ComputeBudget111111111111111111111111111111 success", "Program 3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv invoke [1]", "Program log: Instruction: ThreadKickoff", "Program 3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv consumed 83495 of 1400000 compute units", "Program 3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv success"])
'''