statsig_rust/evaluation/user_agent_parsing/
ua_parser.rs1use std::env;
2
3use crate::evaluation::dynamic_string::DynamicString;
4use crate::user::StatsigUserInternal;
5use crate::{log_w, DynamicValue};
6
7use super::experimental_ua_parser::ExperimentalUserAgentParser;
8use super::third_party_ua_parser::ThirdPartyUserAgentParser;
9
10lazy_static::lazy_static! {
11 static ref USE_EXPERIMENTAL_PARSER: bool = env::var("STATSIG_USE_EXPERIMENTAL_UAPARSER").is_ok_and(|v| v == "true" || v == "1");
12 static ref USER_AGENT_STRING: Option<DynamicString> = Some(DynamicString::from("userAgent".to_string()));
13}
14
15const TAG: &str = "UserAgentParser";
16const UNINITIALIZED_REASON: &str = "UAParserNotLoaded";
17
18pub struct UserAgentParser;
19
20impl UserAgentParser {
21 pub fn get_value_from_user_agent(
22 user: &StatsigUserInternal,
23 field: &Option<DynamicString>,
24 override_reason: &mut Option<&str>,
25 ) -> Option<DynamicValue> {
26 let field_lowered = match field {
27 Some(f) => f.lowercased_value.as_str(),
28 _ => return None,
29 };
30
31 let user_agent = match user.get_user_value(&USER_AGENT_STRING) {
32 Some(v) => match &v.string_value {
33 Some(s) => &s.value,
34 _ => return None,
35 },
36 None => return None,
37 };
38
39 if user_agent.len() > 1000 {
40 return None;
41 }
42
43 if *USE_EXPERIMENTAL_PARSER {
44 ExperimentalUserAgentParser::get_value_from_user_agent(field_lowered, user_agent)
45 } else {
46 let result =
47 ThirdPartyUserAgentParser::get_value_from_user_agent(field_lowered, user_agent);
48
49 match result {
50 Ok(v) => v,
51 Err(_) => {
52 *override_reason = Some(UNINITIALIZED_REASON);
53 log_w!(TAG, "Failed to load UA Parser. Check StatsigOptions.disable_user_agent_parsing and or wait_for_user_agent_init");
54 None
55 }
56 }
57 }
58 }
59
60 pub fn load_parser() {
61 if *USE_EXPERIMENTAL_PARSER {
62 } else {
64 ThirdPartyUserAgentParser::load_parser();
65 }
66 }
67}