nsmcp::SmtpLogTool method execute (public)

 <instance of nsmcp::SmtpLogTool[i]> execute context arguments

Defined in /usr/local/ns/tcl/nsmcp/lib/smtp-tools.tcl

Parameters:
context (required)
arguments (required)

Testcases:
No testcase defined.
Source code:
set options [:options $arguments]
set peers [dict get $options includePeerAddresses]
if {$peers} {${:authorizer} require $context diagnostics.logs.peers.read}
set server [$context server]
set kind [dict get $options log]
set module [dict get $options module]
set source [:path $server $module $kind]
set path [dict get $source path]
set fields [list server string $server module string $module log string $kind  loggingEnabled boolean [dict get $source enabled] sourcePath string $path]
if {$path eq "" || ![file isfile $path] || ![file readable $path]} {
    lappend fields available boolean false reason string {Configured SMTP log is missing or unreadable.}
    return [list {} object $fields]
}
set now [clock seconds]
set from [expr {$now-60*[dict get $options lastMinutes]}]
file stat $path before
set end $before(size)
set start [expr {max(0,$end-${:maxReadBytes})}]
set channel [open $path rb]
try {
    seek $channel $start
    set bytes [read $channel [expr {$end-$start}]]
} finally {close $channel}
set readBytes [string length $bytes]
set discarded 0
if {$start > 0} {
    # Discard the first fragment, even if it happens to be a full line.
    set first [string first \n $bytes]
    if {$first < 0} {set discarded $readBytes; set bytes ""} else {
        set discarded [expr {$first+1}]
        set bytes [string range $bytes $discarded end]
    }
}
set position [expr {$start+$discarded}]
set pending [expr {$bytes ne "" && [string index $bytes end] ne "\n"}]
set lines [split $bytes \n]
set lines [lrange $lines 0 end-1]
set malformed 0
set oversized 0
set otherServers 0
set matches 0
set records {}
foreach line $lines {
    set offset $position
    incr position [expr {[string length $line]+1}]
    if {[string length $line] > ${:maxLineBytes}} {incr oversized; continue}
    if {$line eq ""} continue
    if {[catch {:parse $kind [encoding convertfrom utf-8 [string trimright $line \r]]} record]} {
        incr malformed
        continue
    }
    if {$kind eq "event" && [dict get $record recordedServer] ne $server} {incr otherServers; continue}
    set at [dict get $record timestampSeconds]
    if {$at < $from || $at > $now} continue
    set match true
    foreach key {session event status} {
        if {[dict exists $options $key] && [dict get $options $key] ne [dict get $record $key]} {set match false}
    }
    if {!$match} continue
    set record [:redact $record $peers]
    if {[dict exists $options contains] && [string first [dict get $options contains] $record] < 0} continue
    incr matches
    dict set record offset $offset
    dict set record endOffset $position
    lappend records $record
    set records [lrange $records end-[expr {[dict get $options limit]-1}] end]
}
set changed [catch {file stat $path after}]
if {!$changed} {
    set changed [expr {[list $before(dev) $before(ino)] ne [list $after(dev) $after(ino)] || $after(size) < $end}]
}
if {$changed} {set records {}; set matches 0}
set array {}
set index 0
foreach record [lreverse $records] {
    lappend array $index object [:recordTriples $record]
    incr index
}
set complete [expr {$start == 0 && !$pending && !$changed && !$malformed && !$oversized}]
lappend fields available boolean true from number $from to number $now order string newest-first  records array $array matchesInTail number $matches omittedMatches number [expr {$matches-$index}]  coverage object [list sourceBytes number $end readBytes number $readBytes  initialOffset number $start examinedFromOffset number [expr {$start+$discarded}]  historyUnreadBytes number $start tailOnly boolean [expr {$start > 0}]  pending boolean $pending malformed number $malformed oversized number $oversized  otherServerRecords number $otherServers sourceChanged boolean $changed fileScanComplete boolean $complete rotatedFilesExamined boolean false]
return [list {} object $fields]
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: