@ -212,27 +212,53 @@ const chain_to_list = (requests) => {
return path . values ( ) ;
}
const sort _request _chains = ( by _ip , as _set ) => {
const construct _url _set = ( domain , ref , full _chain ) => {
// this tags the chains with refer using [ref]
if ( ref && ! ref . includes ( domain ) ) {
return [ ` [ ${ ref } ] ` , ... full _chain . slice ( 1 ) ] . join ( " " ) ;
} else {
return full _chain . join ( " " ) ;
}
}
const construct _request _chains = ( by _ip , domain , as _set ) => {
let ip _chains = { } ;
let seen ;
for ( let [ ip , requests ] of Object . entries ( by _ip ) ) {
const chain = as _set ? chain _to _set ( requests ) : chain _to _list ( requests ) ;
const ref = requests [ 0 ] . refer ? ` [ ${ requests [ 0 ] . refer } ] ` : "" ;
const url _set = [ ref , ... chain ] . join ( " " ) ;
// record the initial refer to track entry to the site
const ref = requests [ 0 ] . refer ;
const full _chain = [ ... chain ] ;
const url _set = construct _url _set ( domain , ref , full _chain ) ;
ip _chains [ url _set ] = url _set in ip _chains ? ip _chains [ url _set ] + 1 : 1 ;
// using url as key to count,full_chain
if ( url _set in ip _chains ) {
ip _chains [ url _set ] . count += 1 ;
} else {
ip _chains [ url _set ] = { count : 1 , comes _from : ref , full _chain } ;
}
}
const chains _sorted = Object . entries ( ip _chains ) ;
chains _sorted . sort ( ( a , b ) => b [ 1 ] - a [ 1 ] ) ;
return ip _chains ;
}
const sort _request _chains = ( chains ) => {
const converted = [ ] ;
return chains _sorted ;
for ( let [ url , stats ] of Object . entries ( chains ) ) {
if ( stats . comes _from ) {
converted . push ( [ stats . count , ` [ ${ stats . comes _from } ] ${ stats . full _chain . join ( ' ' ) } ` ] ) ;
} else {
converted . push ( [ stats . count , ` ${ stats . full _chain . join ( ' ' ) } ` ] ) ;
}
}
return converted . sort ( ( a , b ) => b [ 0 ] - a [ 0 ] ) ;
}
const output _results = ( min , chains _sorted ) => {
for ( let [ url , count ] of chains _sorted ) {
const output _results = ( chains _sorted , min ) => {
for ( let [ count , url ] of chains _sorted ) {
if ( count >= min ) {
console . log ( count , url ) ;
}
@ -245,6 +271,8 @@ program
. option ( "--no-set" , "Use a Set instead of a list for chains." )
. option ( "--min <Number>" , "The lowest count to print. Stop at this." , 1 )
. option ( "--errors" , "Show the erorrs so you can fix them." , false )
. option ( "--format <string>" , "Output format, text or json. Ignores min for raw output." , "json" )
. requiredOption ( "--domain <String>" , "Domain for the log. Gets removed as a refer." )
. requiredOption ( "--input <String>" , "Input file." )
. description ( "Processes different web server logs to determine request chain frequency." )
. version ( 0.1 ) ;
@ -256,5 +284,11 @@ OPTS.min = parseInt(OPTS.min);
assert ( ! isNaN ( OPTS . min ) , ` min must be a number, you have ${ OPTS . min } ` ) ;
const [ by _ip , stats ] = await parse _logs ( OPTS . input , OPTS . errors ) ;
const chains _sorted = sort _request _chains ( by _ip , OPTS . set ) ;
output _results ( OPTS . min , chains _sorted ) ;
const chains = construct _request _chains ( by _ip , OPTS . domain , OPTS . set ) ;
const chains _sorted = sort _request _chains ( chains ) ;
if ( OPTS . format === "json" ) {
console . log ( chains ) ;
} else {
output _results ( chains _sorted , OPTS . min ) ;
}