1use std::collections::HashMap;
2use std::env;
3use std::process::Command;
4
5use anyhow::Error;
6use hmac::{Hmac, Mac};
7use opentelemetry::trace::noop::NoopTracerProvider;
8use opentelemetry::trace::TraceError;
9use opentelemetry::{global, KeyValue};
10use opentelemetry_otlp::{Protocol, WithExportConfig};
11use opentelemetry_sdk::trace::config;
12use opentelemetry_sdk::Resource;
13use sha2::Sha256;
14
15pub mod deps;
16pub mod edge;
17pub mod vertex;
18
19type HmacSha256 = Hmac<Sha256>;
20
21pub fn init_tracer() -> Result<(), TraceError> {
22 if let Ok(endpoint) = env::var("OTEL_EXPORTER_OTLP_ENDPOINT") {
23 let protocol = match env::var("OTEL_EXPORTER_OTLP_PROTOCOL") {
24 Ok(protocol) => match protocol.as_str() {
25 "grpc" => Protocol::Grpc,
26 _ => Protocol::HttpBinary,
27 },
28 Err(_) => Protocol::HttpBinary,
29 };
30 let export_config = opentelemetry_otlp::ExportConfig {
31 endpoint,
32 protocol,
33 ..opentelemetry_otlp::ExportConfig::default()
34 };
35
36 let mut headers = HashMap::new();
37 let tracing = opentelemetry_otlp::new_pipeline().tracing();
38
39 if let Ok(api_key) = env::var("OTLP_API_KEY") {
40 headers.insert("x-api-key".into(), api_key);
41 }
42
43 if let Ok(honeycomb_api_key) = env::var("HONEYCOMB_API_KEY") {
44 headers.insert("x-honeycomb-team".into(), honeycomb_api_key);
45 }
46
47 if let Ok(honeycomb_dataset) = env::var("HONEYCOMB_DATASET") {
48 headers.insert("x-honeycomb-dataset".into(), honeycomb_dataset);
49 }
50
51 if let Ok(baselime_dataset) = env::var("BASELIME_DATASET") {
52 headers.insert("x-baselime-dataset".into(), baselime_dataset);
53 }
54
55 let tracing = match protocol {
56 Protocol::Grpc => tracing.with_exporter(
57 opentelemetry_otlp::new_exporter()
58 .tonic()
59 .with_export_config(export_config),
60 ),
61 _ => tracing.with_exporter(
62 opentelemetry_otlp::new_exporter()
63 .http()
64 .with_export_config(export_config)
65 .with_headers(headers),
66 ),
67 };
68
69 let _ = tracing
70 .with_trace_config(config().with_resource(Resource::new(vec![
71 KeyValue::new("service.name", "fluentci-engine"),
72 KeyValue::new("service.namespace", "fluentci-core"),
73 KeyValue::new("service.version", env!("CARGO_PKG_VERSION")),
74 KeyValue::new("exporter", "otlp"),
75 ])))
76 .install_batch(opentelemetry_sdk::runtime::Tokio)?;
77
78 return Ok(());
79 }
80
81 if let Ok(endpoint) = env::var("OTEL_EXPORTER_JAEGER_AGENT_HOST") {
82 #[allow(deprecated)]
83 let _ = opentelemetry_jaeger::new_agent_pipeline()
84 .with_endpoint(endpoint)
85 .with_service_name("fluentci-core")
86 .with_trace_config(config().with_resource(Resource::new(vec![
87 KeyValue::new("service.name", "fluentci-engine"),
88 KeyValue::new("service.namespace", "fluentci-core"),
89 KeyValue::new("service.version", env!("CARGO_PKG_VERSION")),
90 KeyValue::new("exporter", "jaeger"),
91 ])))
92 .install_simple()?;
93
94 return Ok(());
95 }
96
97 if let Ok(endpoint) = env::var("OTEL_EXPORTER_ZIPKIN_ENDPOINT") {
98 let _ = opentelemetry_zipkin::new_pipeline()
99 .with_service_name("fluentci-core")
100 .with_collector_endpoint(endpoint)
101 .install_batch(opentelemetry_sdk::runtime::Tokio)?;
102
103 return Ok(());
104 }
105
106 let provider = NoopTracerProvider::new();
107 let _ = global::set_tracer_provider(provider);
108 Ok(())
109}
110
111pub fn set_git_repo_metadata() -> Result<(), Error> {
112 let child = Command::new("sh")
113 .arg("-c")
114 .arg("git log -1 --pretty=%s 2> /dev/null")
115 .stdout(std::process::Stdio::piped())
116 .spawn()?;
117 let output = child.wait_with_output()?;
118 let commit_message = String::from_utf8(output.stdout)?;
119
120 let child = Command::new("sh")
121 .arg("-c")
122 .arg("git rev-parse --abbrev-ref HEAD 2> /dev/null")
123 .stdout(std::process::Stdio::piped())
124 .spawn()?;
125 let output = child.wait_with_output()?;
126 let branch = String::from_utf8(output.stdout)?;
127
128 let child = Command::new("sh")
129 .arg("-c")
130 .arg("git log -1 --pretty=%h 2> /dev/null")
131 .stdout(std::process::Stdio::piped())
132 .spawn()?;
133 let output = child.wait_with_output()?;
134 let commit_hash = String::from_utf8(output.stdout)?;
135
136 let child = Command::new("sh")
137 .arg("-c")
138 .arg("git remote get-url origin 2> /dev/null")
139 .stdout(std::process::Stdio::piped())
140 .spawn()?;
141 let output = child.wait_with_output()?;
142 let remote_url = String::from_utf8(output.stdout)?;
143
144 let child = Command::new("sh")
145 .arg("-c")
146 .arg("git log -1 --pretty=%an 2> /dev/null")
147 .stdout(std::process::Stdio::piped())
148 .spawn()?;
149 let output = child.wait_with_output()?;
150 let author = String::from_utf8(output.stdout)?;
151
152 env::set_var("GIT_COMMIT_MESSAGE", commit_message.trim());
153 env::set_var("GIT_BRANCH", branch.trim());
154 env::set_var("GIT_COMMIT_HASH", commit_hash.trim());
155 env::set_var("GIT_REMOTE_URL", remote_url.trim());
156 env::set_var("GIT_AUTHOR", author.trim());
157 Ok(())
158}
159
160pub fn get_hmac(id: String, name: String) -> Result<String, Error> {
161 let mut mac = HmacSha256::new_from_slice(&id.into_bytes())?;
162 mac.update(name.as_bytes());
163 let key = mac.finalize().into_bytes();
164 Ok(hex::encode(key))
165}