send_trace_to_jaeger/
main.rs1use std::{
2 env::args,
3 fs::File,
4 io::{self, BufRead},
5 path::Path,
6};
7
8use reqwest::blocking::Client;
9use serde_json::{Map, Number, Value};
10
11fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
13where
14 P: AsRef<Path>,
15{
16 let file = File::open(filename)?;
17 Ok(io::BufReader::new(file).lines())
18}
19
20fn log_web_url(jaeger_web_ui_url: &str, trace_id: &str) {
22 println!("Jaeger trace will be available on {jaeger_web_ui_url}/trace/{trace_id}")
23}
24
25fn send_json_to_zipkin(zipkin_api: &str, value: String) {
27 let client = Client::new();
28
29 let res = client
30 .post(zipkin_api)
31 .header("Content-Type", "application/json")
32 .body(value)
33 .send()
34 .expect("Failed to send request");
35
36 if !res.status().is_success() {
37 println!("body = {:?}", res.text());
38 }
39}
40
41fn pad_zeros(num: u64) -> String {
43 let mut num_str = num.to_string();
44 while num_str.len() < 16 {
45 num_str = format!("0{num_str}");
46 }
47 num_str
48}
49
50fn main() {
51 let service_name = "nextjs";
52 let ipv4 = "127.0.0.1";
53 let port = 9411;
54 let zipkin_url = format!("http://{ipv4}:{port}");
55 let jaeger_web_ui_url = format!("http://{ipv4}:16686");
56 let zipkin_api = format!("{zipkin_url}/api/v2/spans");
57 let mut logged_url = false;
58
59 let mut local_endpoint = Map::new();
60 local_endpoint.insert(
61 "serviceName".to_string(),
62 Value::String(service_name.to_string()),
63 );
64 local_endpoint.insert("ipv4".to_string(), Value::String(ipv4.to_string()));
65 local_endpoint.insert("port".to_string(), Value::Number(Number::from(port)));
66
67 let first_arg = args().nth(1).expect("Please provide a file name");
68
69 if let Ok(lines) = read_lines(first_arg) {
70 for json_to_parse in lines.map_while(Result::ok) {
71 let v = match serde_json::from_str::<Vec<Value>>(&json_to_parse) {
72 Ok(v) => v
73 .into_iter()
74 .map(|mut data| {
75 if !logged_url {
76 log_web_url(&jaeger_web_ui_url, data["traceId"].as_str().unwrap());
77 logged_url = true;
78 }
79 data["localEndpoint"] = Value::Object(local_endpoint.clone());
80
81 data["id"] = Value::String(pad_zeros(data["id"].as_u64().unwrap()));
82 if data["parentId"] != Value::Null {
83 data["parentId"] =
84 Value::String(pad_zeros(data["parentId"].as_u64().unwrap()));
85 }
86
87 if let Some(tags) = data["tags"].as_object_mut() {
88 for (_, value) in tags.iter_mut() {
89 if value.is_boolean() {
90 let bool_val = value.as_bool().unwrap();
91 *value = serde_json::Value::String(bool_val.to_string());
92 }
93 }
94 }
95
96 data
97 })
98 .collect::<Value>(),
99 Err(e) => {
100 println!("{e}");
101 continue;
102 }
103 };
104
105 let json_map = serde_json::to_string(&v).expect("Failed to serialize");
106
107 send_json_to_zipkin(&zipkin_api, json_map);
110 }
111 }
112}