pact_plugin_driver/
plugin_log_sink.rs1use std::sync::RwLock;
4
5use lazy_static::lazy_static;
6use tracing::{debug, error, info, warn};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum PluginLogSource {
11 Stderr,
13 LogRpc,
15}
16
17#[derive(Debug, Clone)]
19pub struct PluginLogEntry {
20 pub plugin_name: String,
22 pub plugin_instance_id: String,
24 pub test_run_id: Option<String>,
26 pub level: String,
28 pub message: String,
30 pub target: Option<String>,
32 pub timestamp_ms: i64,
34 pub source: PluginLogSource,
36}
37
38pub trait PluginLogSink: Send + Sync {
45 fn log(&self, entry: &PluginLogEntry);
46}
47
48struct DefaultPluginLogSink;
49
50fn is_transport_target(target: &str) -> bool {
51 target.starts_with("h2::") || target.starts_with("tower::") ||
52 target.starts_with("tonic::") || target.starts_with("hyper_util::") ||
53 target.starts_with("hyper::")
54}
55
56impl PluginLogSink for DefaultPluginLogSink {
57 fn log(&self, entry: &PluginLogEntry) {
58 if entry.source != PluginLogSource::LogRpc {
59 return;
60 }
61 if entry.level.to_uppercase() == "TRACE" {
62 return;
63 }
64 if entry.target.as_deref().map(is_transport_target).unwrap_or(false) {
65 return;
66 }
67 let plugin = &entry.plugin_name;
68 let instance = &entry.plugin_instance_id;
69 let msg = &entry.message;
70 let run_id = entry.test_run_id.as_deref().unwrap_or("");
71 match entry.level.to_uppercase().as_str() {
72 "DEBUG" => debug!(plugin_name = %plugin, plugin_instance = %instance, test_run_id = %run_id, "{}", msg),
73 "INFO" => info!(plugin_name = %plugin, plugin_instance = %instance, test_run_id = %run_id, "{}", msg),
74 "WARN" => warn!(plugin_name = %plugin, plugin_instance = %instance, test_run_id = %run_id, "{}", msg),
75 _ => error!(plugin_name = %plugin, plugin_instance = %instance, test_run_id = %run_id, "{}", msg),
76 }
77 }
78}
79
80lazy_static! {
81 static ref PLUGIN_LOG_SINK: RwLock<Box<dyn PluginLogSink>> =
82 RwLock::new(Box::new(DefaultPluginLogSink));
83}
84
85pub fn set_plugin_log_sink(sink: Box<dyn PluginLogSink>) {
87 *PLUGIN_LOG_SINK.write().unwrap() = sink;
88}
89
90pub(crate) fn emit_plugin_log(entry: &PluginLogEntry) {
92 PLUGIN_LOG_SINK.read().unwrap().log(entry);
93}