vector_vrl_web_playground/
lib.rs1use std::collections::BTreeMap;
2
3use gloo_utils::format::JsValueSerdeExt;
4use serde::{Deserialize, Serialize};
5use vrl::{
6 compiler::{
7 CompileConfig, TargetValue, TimeZone, TypeState, compile_with_state,
8 runtime::{Runtime, Terminate},
9 },
10 diagnostic::{DiagnosticList, Formatter},
11 value::{Secrets, Value},
12};
13use wasm_bindgen::prelude::*;
14
15pub mod built_info {
16 include!(concat!(env!("OUT_DIR"), "/built.rs"));
17}
18
19#[derive(Serialize, Deserialize)]
20pub struct Input {
21 pub program: String,
22 pub event: Value,
23}
24
25impl Input {
26 pub fn new(program: &str, event: Value) -> Self {
27 Self {
28 program: program.to_owned(),
29 event,
30 }
31 }
32}
33
34#[derive(Deserialize, Serialize)]
37pub struct VrlCompileResult {
38 pub runtime_result: Value,
39 pub target_value: Value,
40 pub elapsed_time: Option<f64>,
41}
42
43#[derive(Deserialize, Serialize, Default)]
44pub struct VrlDiagnosticResult {
45 pub list: Vec<String>,
46 pub msg: String,
47 pub msg_colorized: String,
48}
49
50impl VrlDiagnosticResult {
51 fn new(program: &str, diagnostic_list: DiagnosticList) -> Self {
52 Self {
53 list: diagnostic_list
54 .clone()
55 .into_iter()
56 .map(|diag| String::from(diag.message()))
57 .collect(),
58 msg: Formatter::new(program, diagnostic_list.clone()).to_string(),
59 msg_colorized: Formatter::new(program, diagnostic_list)
60 .colored()
61 .to_string(),
62 }
63 }
64
65 fn new_runtime_error(program: &str, terminate: Terminate) -> Self {
66 Self {
67 list: Vec::with_capacity(1),
68 msg: Formatter::new(program, terminate.clone().get_expression_error()).to_string(),
69 msg_colorized: Formatter::new(program, terminate.get_expression_error())
70 .colored()
71 .to_string(),
72 }
73 }
74}
75
76fn compile(
77 mut input: Input,
78 tz_str: Option<String>,
79) -> Result<VrlCompileResult, VrlDiagnosticResult> {
80 let mut functions = vrl::stdlib::all();
81 functions.extend(vector_vrl_functions::all());
82 functions.extend(enrichment::vrl_functions());
83
84 let event = &mut input.event;
85 let state = TypeState::default();
86 let mut runtime = Runtime::default();
87 let config = CompileConfig::default();
88
89 let timezone = match tz_str.as_deref() {
90 None | Some("") | Some("Default") => TimeZone::default(),
92 Some(other) => match other.parse() {
93 Ok(tz) => TimeZone::Named(tz),
94 Err(_) => {
95 let error_message = format!("Invalid timezone identifier: '{other}'");
98 return Err(VrlDiagnosticResult {
99 list: vec![error_message.clone()],
100 msg: error_message.clone(),
101 msg_colorized: error_message,
102 });
103 }
104 },
105 };
106
107 let mut target_value = TargetValue {
108 value: event.clone(),
109 metadata: Value::Object(BTreeMap::new()),
110 secrets: Secrets::new(),
111 };
112
113 let compilation_result = match compile_with_state(&input.program, &functions, &state, config) {
114 Ok(result) => result,
115 Err(diagnostics) => return Err(VrlDiagnosticResult::new(&input.program, diagnostics)),
116 };
117
118 let (result, elapsed_time) =
119 if let Some(performance) = web_sys::window().and_then(|w| w.performance()) {
120 let start_time = performance.now();
121 let result = runtime.resolve(&mut target_value, &compilation_result.program, &timezone);
122 let end_time = performance.now();
123 (result, Some(end_time - start_time))
124 } else {
125 let result = runtime.resolve(&mut target_value, &compilation_result.program, &timezone);
127 (result, None)
128 };
129
130 match result {
131 Ok(runtime_result) => Ok(VrlCompileResult {
132 runtime_result, target_value: target_value.value, elapsed_time,
135 }),
136 Err(err) => Err(VrlDiagnosticResult::new_runtime_error(&input.program, err)),
137 }
138}
139
140#[wasm_bindgen]
142pub fn run_vrl(incoming: &JsValue, tz_str: &str) -> JsValue {
143 let input: Input = incoming.into_serde().unwrap();
144
145 match compile(input, Some(tz_str.to_string())) {
146 Ok(res) => JsValue::from_serde(&res).unwrap(),
147 Err(err) => JsValue::from_serde(&err).unwrap(),
148 }
149}
150
151#[wasm_bindgen]
152pub fn vector_version() -> String {
153 built_info::VECTOR_VERSION.to_string()
154}
155
156#[wasm_bindgen]
157pub fn vector_link() -> String {
158 built_info::VECTOR_LINK.to_string()
159}
160
161#[wasm_bindgen]
162pub fn vrl_version() -> String {
163 built_info::VRL_VERSION.to_string()
164}
165
166#[wasm_bindgen]
167pub fn vrl_link() -> String {
168 built_info::VRL_LINK.to_string()
169}