@@ -28,21 +28,18 @@ export class LogParser extends EventEmitter {
2828 }
2929
3030 async setLogFile ( filePath ) {
31- // Stop existing tail if any
3231 if ( this . tail ) {
3332 this . tail . unwatch ( ) ;
3433 }
3534
36- // Check if file exists
3735 try {
3836 await fs . access ( filePath ) ;
3937 } catch ( error ) {
4038 throw new Error ( `Log file not found: ${ filePath } ` ) ;
4139 }
4240
43- // Start tailing the file
4441 this . tail = new Tail ( filePath , {
45- fromBeginning : false ,
42+ fromBeginning : true , // Read from the beginning to get all logs
4643 follow : true ,
4744 logger : console
4845 } ) ;
@@ -55,39 +52,20 @@ export class LogParser extends EventEmitter {
5552 console . error ( 'Tail error:' , error ) ;
5653 this . emit ( 'error' , error ) ;
5754 } ) ;
58-
59- // Process existing file content
60- await this . processExistingFile ( filePath ) ;
61- }
62-
63- async processExistingFile ( filePath ) {
64- try {
65- const content = await fs . readFile ( filePath , 'utf-8' ) ;
66- const lines = content . split ( '\n' ) . filter ( line => line . trim ( ) ) ;
67-
68- // Process last 1000 lines for initial data
69- const lastLines = lines . slice ( - 1000 ) ;
70- for ( const line of lastLines ) {
71- await this . parseLine ( line , false ) ; // Don't emit events for initial load
72- }
73- } catch ( error ) {
74- console . error ( 'Error processing existing file:' , error ) ;
75- }
7655 }
7756
7857 async parseLine ( line , emit = true ) {
7958 try {
8059 const log = JSON . parse ( line ) ;
8160
82- // Extract relevant fields
8361 const parsedLog = {
8462 id : `${ Date . now ( ) } -${ Math . random ( ) } ` ,
8563 timestamp : log . time || new Date ( ) . toISOString ( ) ,
8664 clientIP : this . extractIP ( log . ClientAddr || log . request_ClientAddr || '' ) ,
8765 method : log . RequestMethod || log . request_method || 'GET' ,
8866 path : log . RequestPath || log . request_path || '' ,
8967 status : parseInt ( log . DownstreamStatus || log . downstream_status || 0 ) ,
90- responseTime : parseFloat ( log . Duration || log . duration || 0 ) * 1000 , // Convert to ms
68+ responseTime : parseFloat ( log . Duration || log . duration || 0 ) * 1000 ,
9169 serviceName : log . ServiceName || log . service_name || 'unknown' ,
9270 routerName : log . RouterName || log . router_name || 'unknown' ,
9371 host : log . RequestHost || log . request_host || '' ,
@@ -97,7 +75,6 @@ export class LogParser extends EventEmitter {
9775 city : null
9876 } ;
9977
100- // Get geolocation (with caching)
10178 if ( parsedLog . clientIP ) {
10279 const geoData = await getGeoLocation ( parsedLog . clientIP ) ;
10380 if ( geoData ) {
@@ -109,64 +86,51 @@ export class LogParser extends EventEmitter {
10986 }
11087 }
11188
112- // Update stats
11389 this . updateStats ( parsedLog ) ;
11490
115- // Add to logs array
11691 this . logs . unshift ( parsedLog ) ;
11792 if ( this . logs . length > this . maxLogs ) {
11893 this . logs . pop ( ) ;
11994 }
12095
121- // Emit event for real-time updates
12296 if ( emit ) {
12397 this . emit ( 'newLog' , parsedLog ) ;
12498 }
12599
126100 } catch ( error ) {
101+ // It's possible that some lines in the log are not valid JSON.
102+ // We'll log the error but continue processing.
127103 console . error ( 'Error parsing log line:' , error , line ) ;
128104 }
129105 }
130106
131107 extractIP ( clientAddr ) {
132- // Extract IP from "IP:Port" format
133108 const match = clientAddr . match ( / ^ ( \d + \. \d + \. \d + \. \d + ) : \d + $ / ) ;
134109 return match ? match [ 1 ] : clientAddr ;
135110 }
136111
137112 updateStats ( log ) {
138113 this . stats . totalRequests ++ ;
139114
140- // Status codes
141115 const statusGroup = Math . floor ( log . status / 100 ) * 100 ;
142116 this . stats . statusCodes [ log . status ] = ( this . stats . statusCodes [ log . status ] || 0 ) + 1 ;
143117
144118 if ( statusGroup === 200 ) this . stats . requests2xx ++ ;
145119 else if ( statusGroup === 400 ) this . stats . requests4xx ++ ;
146120 else if ( statusGroup === 500 ) this . stats . requests5xx ++ ;
147121
148- // Services
149122 this . stats . services [ log . serviceName ] = ( this . stats . services [ log . serviceName ] || 0 ) + 1 ;
150-
151- // Routers
152123 this . stats . routers [ log . routerName ] = ( this . stats . routers [ log . routerName ] || 0 ) + 1 ;
153-
154- // Methods
155124 this . stats . methods [ log . method ] = ( this . stats . methods [ log . method ] || 0 ) + 1 ;
156-
157- // Top IPs
158125 this . stats . topIPs [ log . clientIP ] = ( this . stats . topIPs [ log . clientIP ] || 0 ) + 1 ;
159126
160- // Countries
161127 if ( log . country ) {
162128 this . stats . countries [ log . country ] = ( this . stats . countries [ log . country ] || 0 ) + 1 ;
163129 }
164130
165- // Calculate average response time
166131 const totalResponseTime = this . logs . reduce ( ( acc , l ) => acc + l . responseTime , 0 ) ;
167132 this . stats . avgResponseTime = this . logs . length > 0 ? totalResponseTime / this . logs . length : 0 ;
168133
169- // Calculate requests per second
170134 const now = Date . now ( ) ;
171135 if ( now - this . lastTimestamp >= 1000 ) {
172136 this . stats . requestsPerSecond = this . requestsInLastSecond ;
@@ -178,13 +142,11 @@ export class LogParser extends EventEmitter {
178142 }
179143
180144 async getStats ( ) {
181- // Get top 10 IPs
182145 const topIPs = Object . entries ( this . stats . topIPs )
183146 . sort ( ( [ , a ] , [ , b ] ) => b - a )
184147 . slice ( 0 , 10 )
185148 . map ( ( [ ip , count ] ) => ( { ip, count } ) ) ;
186149
187- // Get top countries
188150 const topCountries = Object . entries ( this . stats . countries )
189151 . sort ( ( [ , a ] , [ , b ] ) => b - a )
190152 . slice ( 0 , 10 )
@@ -198,10 +160,9 @@ export class LogParser extends EventEmitter {
198160 } ;
199161 }
200162
201- async getLogs ( { page = 1 , limit = 100 , filters = { } } ) {
163+ async getLogs ( { page = 1 , limit = 50 , filters = { } } ) {
202164 let filteredLogs = [ ...this . logs ] ;
203165
204- // Apply filters
205166 if ( filters . service ) {
206167 filteredLogs = filteredLogs . filter ( log => log . serviceName === filters . service ) ;
207168 }
@@ -212,7 +173,6 @@ export class LogParser extends EventEmitter {
212173 filteredLogs = filteredLogs . filter ( log => log . routerName === filters . router ) ;
213174 }
214175
215- // Pagination
216176 const start = ( page - 1 ) * limit ;
217177 const end = start + limit ;
218178 const paginatedLogs = filteredLogs . slice ( start , end ) ;
@@ -240,4 +200,4 @@ export class LogParser extends EventEmitter {
240200
241201 return { countries } ;
242202 }
243- }
203+ }
0 commit comments