Class Relations
- class: ::nx::EnsembleObject
![[i]](/resources/acs-subsite/ZoomIn16.gif)
::nx::EnsembleObject create ::ns::stats::Sampler::slot::__sampling
Methods (to be applied on the object)
history (scripted)
if {$from<0 || $to<=$from || $to-$from>86400 || $to>[clock seconds]
|| $limit<1 || $limit>180 || $cursor<0} {
error "expected an epoch window up to 24 hours, limit 1..180 and nonnegative cursor"
}
if {[string length $server]>512 || [string first \x00 $server]>=0} {
error "invalid server name"
}
:locked {
set retained [nsv_get ns_stats recent]
set dropped [nsv_get ns_stats recentDroppedThrough]
}
set records {}
set gaps {}
set restarts {}
set resets 0
set previous {}
set first {}
set last {}
set more false
foreach record $retained {
set stamp [dict get $record timestamp]
if {$first eq ""} {
set first $stamp
}
set last $stamp
if {$stamp<$from*1000000 || $stamp<=$cursor} {
set previous $record
continue
}
if {$stamp>=$to*1000000} {
if {$previous ne ""} {
set delta [expr {($stamp-[dict get $previous timestamp])/1000000.0}]
if {$delta>1.5*max([dict get $previous sampling intervalSeconds],
[dict get $record sampling intervalSeconds])} {
lappend gaps [dict create from [dict get $previous sampling to] to [dict get $record sampling to]]
}
}
break
}
if {[llength $records]>=$limit} {
set more true
break
}
if {![dict get $record sampling ready]} {
incr resets
}
if {$previous ne ""} {
if {[dict get $previous instance] ne [dict get $record instance]} {
lappend restarts [dict get $record sampling to]
}
set delta [expr {($stamp-[dict get $previous timestamp])/1000000.0}]
if {$delta>1.5*max([dict get $previous sampling intervalSeconds],
[dict get $record sampling intervalSeconds])} {
lappend gaps [dict create from [dict get $previous sampling to] to [dict get $record sampling to]]
}
}
lappend records [:selectServer [dict remove $record cpu] $server false]
set previous $record
}
if {$retained ne ""} {
set first [dict get [lindex $retained 0] timestamp]
set last [dict get [lindex $retained end] timestamp]
}
set overlap [expr {$dropped ne "" && $dropped>=$from*1000000}]
if {!$more && $cursor>0} {
set window [:sampling history -from $from -to $to -server $server -limit 180]
set coverage [dict get $window coverage]
return [dict create schemaVersion 1 source memory from $from to $to records $records nextCursor {} more false retentionSeconds 900 maxSamples 180 coverage $coverage]
}
set complete [expr {$first ne "" && $first<=$from*1000000 && $last>=$to*1000000
&& !$more && $cursor==0 && !$overlap && $gaps eq ""
&& $restarts eq "" && $resets==0}]
set next {}
if {$more} {
set next [dict get [lindex $records end] timestamp]
}
return [dict create schemaVersion 1 source memory from $from to $to records $records nextCursor $next more $more retentionSeconds 900 maxSamples 180 coverage [dict create complete $complete windowExamined [expr {!$more && $cursor==0}] retainedFrom [expr {$first eq "" ? 0 : $first/1000000.0}] retainedTo [expr {$last eq "" ? 0 : $last/1000000.0}] gaps $gaps restartBoundaries $restarts resetSamples $resets evictionOrFailureOverlap $overlap droppedThrough $dropped]]start (scripted)
set interval [ns_baseunit -time $interval]
if {$interval < 1 || $interval > 3600} {
error "interval must be 1..3600 seconds"
}
:locked {
set state [nsv_get ns_stats control]
if {[dict get $state running]} {
if {[dict get $state interval]!=$interval} {
error "sampler already running with a different interval; stop it before reconfiguring"
}
} else {
dict incr state generation
dict set state running true
dict set state interval $interval
dict set state busy false
dict set state scheduler [ns_schedule_proc -thread $interval [self] sampling tick]
nsv_set ns_stats pair {}
nsv_set ns_stats control $state
}
}
return [:sampling status]status (scripted)
set result [nsv_get ns_stats control]
dict unset result busy
dict unset result generation
set sample [nsv_get ns_stats pair]
dict set result ready [expr {$sample ne "" && [dict get $sample sampling ready]}]
dict set result latestAt {}
dict set result ageSeconds {}
if {$sample ne ""} {
set stamp [dict get $sample timestamp]
dict set result latestAt [expr {$stamp/1000000.0}]
dict set result ageSeconds [expr {max(0,([clock microseconds]-$stamp)/1000000.0)}]
}
return $resultstop (scripted)
:locked {
set state [nsv_get ns_stats control]
if {[dict get $state running]} {
ns_unschedule_proc [dict get $state scheduler]
}
dict set state running false
dict incr state generation
dict set state busy false
dict set state scheduler {}
nsv_set ns_stats control $state
}
return [:sampling status]tick (scripted)
set generation {}
:locked {
set state [nsv_get ns_stats control]
if {![dict get $state running] || [dict get $state busy]} {
return
}
set generation [dict get $state generation]
dict set state busy true
nsv_set ns_stats control $state
}
if {$generation eq ""} {
return
}
try {
set current [:snapshot]
:locked {
set state [nsv_get ns_stats control]
if {$generation!=[dict get $state generation]} {
return
}
set pair [nsv_get ns_stats pair]
set previous [expr {$pair eq "" ? "" : [dict get $pair raw]}]
set sample [:calculate $current $previous [dict get $state interval] [dict get $state instance]]
:retainSample $sample
dict set sample raw $current
nsv_set ns_stats pair $sample
dict set state busy false
dict set state lastError {}
nsv_set ns_stats control $state
}
} on error {message options} {
:locked {
set state [nsv_get ns_stats control]
if {$generation == [dict get $state generation]} {
dict set state busy false
dict incr state errors
dict set state lastError $message
nsv_set ns_stats control $state
}
}
ns_log warning "ns_stats: sampling failed: $message"
}