nsmcp::SmtpLogTool method execute (public)
<instance of nsmcp::SmtpLogTool> 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
![[i]](/resources/acs-subsite/ZoomIn16.gif)