11//! Utilities to parse Torrust Tracker logs.
22use serde:: { Deserialize , Serialize } ;
33
4- const UDP_TRACKER_PATTERN : & str = "UDP TRACKER: Started on: udp://" ;
5- const HTTP_TRACKER_PATTERN : & str = "HTTP TRACKER: Started on: " ;
6- const HEALTH_CHECK_PATTERN : & str = "HEALTH CHECK API: Started on: " ;
4+ const INFO_LOG_LEVEL : & str = "INFO" ;
5+
6+ const UDP_TRACKER_TARGET : & str = "UDP TRACKER" ;
7+ const UDP_TRACKER_SOCKET_ADDR_START_PATTERN : & str = "Started on: udp://" ;
8+
9+ const HTTP_TRACKER_TARGET : & str = "HTTP TRACKER" ;
10+ const HTTP_TRACKER_URL_START_PATTERN : & str = "Started on: " ;
11+
12+ const HEALTH_CHECK_TARGET : & str = "HEALTH CHECK API" ;
13+ const HEALTH_CHECK_URL_START_PATTERN : & str = "Started on: " ;
714
815#[ derive( Serialize , Deserialize , Debug , Default ) ]
916pub struct RunningServices {
@@ -59,11 +66,11 @@ impl RunningServices {
5966 let mut health_checks: Vec < String > = Vec :: new ( ) ;
6067
6168 for line in logs. lines ( ) {
62- if let Some ( address) = Self :: extract_address_if_matches ( line, UDP_TRACKER_PATTERN ) {
69+ if let Some ( address) = Self :: extract_udp_tracker_url ( line) {
6370 udp_trackers. push ( address) ;
64- } else if let Some ( address) = Self :: extract_address_if_matches ( line, HTTP_TRACKER_PATTERN ) {
71+ } else if let Some ( address) = Self :: extract_http_tracker_url ( line) {
6572 http_trackers. push ( address) ;
66- } else if let Some ( address) = Self :: extract_address_if_matches ( line, HEALTH_CHECK_PATTERN ) {
73+ } else if let Some ( address) = Self :: extract_health_check_api_url ( line) {
6774 health_checks. push ( format ! ( "{address}/health_check" ) ) ;
6875 }
6976 }
@@ -75,9 +82,32 @@ impl RunningServices {
7582 }
7683 }
7784
78- fn extract_address_if_matches ( line : & str , pattern : & str ) -> Option < String > {
79- line. find ( pattern)
80- . map ( |start| Self :: replace_wildcard_ip_with_localhost ( line[ start + pattern. len ( ) ..] . trim ( ) ) )
85+ fn extract_udp_tracker_url ( line : & str ) -> Option < String > {
86+ if !line. contains ( INFO_LOG_LEVEL ) || !line. contains ( UDP_TRACKER_TARGET ) {
87+ return None ;
88+ } ;
89+
90+ line. find ( UDP_TRACKER_SOCKET_ADDR_START_PATTERN ) . map ( |start| {
91+ Self :: replace_wildcard_ip_with_localhost ( line[ start + UDP_TRACKER_SOCKET_ADDR_START_PATTERN . len ( ) ..] . trim ( ) )
92+ } )
93+ }
94+
95+ fn extract_http_tracker_url ( line : & str ) -> Option < String > {
96+ if !line. contains ( INFO_LOG_LEVEL ) || !line. contains ( HTTP_TRACKER_TARGET ) {
97+ return None ;
98+ } ;
99+
100+ line. find ( HTTP_TRACKER_URL_START_PATTERN )
101+ . map ( |start| Self :: replace_wildcard_ip_with_localhost ( line[ start + HTTP_TRACKER_URL_START_PATTERN . len ( ) ..] . trim ( ) ) )
102+ }
103+
104+ fn extract_health_check_api_url ( line : & str ) -> Option < String > {
105+ if !line. contains ( INFO_LOG_LEVEL ) || !line. contains ( HEALTH_CHECK_TARGET ) {
106+ return None ;
107+ } ;
108+
109+ line. find ( HEALTH_CHECK_URL_START_PATTERN )
110+ . map ( |start| Self :: replace_wildcard_ip_with_localhost ( line[ start + HEALTH_CHECK_URL_START_PATTERN . len ( ) ..] . trim ( ) ) )
81111 }
82112
83113 fn replace_wildcard_ip_with_localhost ( address : & str ) -> String {
@@ -127,6 +157,15 @@ mod tests {
127157 assert_eq ! ( running_services. health_checks, vec![ "http://127.0.0.1:1313/health_check" ] ) ;
128158 }
129159
160+ #[ test]
161+ fn it_should_support_colored_output ( ) {
162+ let logs = "\x1b [2m2024-06-14T14:40:13.028824Z\x1b [0m \x1b [33mINFO\x1b [0m \x1b [2mUDP TRACKER\x1b [0m: \x1b [37mStarted on: udp://0.0.0.0:6969\x1b [0m" ;
163+
164+ let running_services = RunningServices :: parse_from_logs ( logs) ;
165+
166+ assert_eq ! ( running_services. udp_trackers, vec![ "127.0.0.1:6969" ] ) ;
167+ }
168+
130169 #[ test]
131170 fn it_should_ignore_logs_with_no_matching_lines ( ) {
132171 let logs = "[Other Service][INFO] Started on: 0.0.0.0:7070" ;
0 commit comments