nsmcp::AccessAnalytics method correlateWarnings (public)
<instance of nsmcp::AccessAnalytics> correlateWarnings samples \ redactor
Defined in /usr/local/ns/tcl/nsmcp/access-analytics.tcl
Correlate bounded warning examples with retained access records. Use the existing start-time index only; do not scan raw logs or trigger ingestion or historical backfill. Peer addresses are never selected.
- Parameters:
- samples (required)
- Up to three dictionaries with requestIdentifier and timestamp; optional system-log User-Agent fields take precedence over the cached agent.
- redactor (required)
- Redactor object applied before returning diagnostic evidence.
- Returns:
- Rooted JSON triples with sampled evidence and explicit missing and ambiguous counts.
- Testcases:
- No testcase defined.
Source code: if {[llength $samples] > 3} { error "Too many warning correlation samples" } set fields {} set matched 0 set missing 0 set ambiguous 0 set i 0 set db [${:database} connect] try { foreach sample $samples { set request_id [dict get $sample requestIdentifier] set at [dict get $sample timestamp] if {![::nsmcp::logRecordParser validConnectionIdentifier $request_id] || ![string match "-conn:[ns_info server]:*" $request_id] || ![string is double -strict $at]} { incr missing continue } set lower [expr {$at-60}] set upper [expr {$at+1}] set rows [$db execute {SELECT request_id,start,path,pool,method,status,authenticationState,userAgent FROM nsmcp_access_requests WHERE start >= :lower AND start <= :upper AND request_id=:request_id LIMIT 2}] if {[llength $rows] == 0} { incr missing continue } if {[llength $rows] > 1} { incr ambiguous continue } set row [lindex $rows 0] set item {} set uaSource access-cache set authSource access-cache if {[dict exists $sample authenticationState] && [dict get $sample authenticationState] in {anonymous authenticated}} { dict set row authenticationState [dict get $sample authenticationState] set authSource system-log } set uaTruncated [expr {[string length [dict get $row userAgent]] >= 1024}] if {[dict exists $sample userAgent]} { dict set row userAgent [dict get $sample userAgent] set uaSource system-log set uaTruncated [dict get $sample userAgentMayBeTruncated] } foreach key {path pool method authenticationState userAgent} { lappend item $key string [$redactor message [dict get $row $key]] } lappend item requestIdentifier string $request_id start number [dict get $row start] status number [dict get $row status] warningTimestamp number $at authenticationSource string $authSource userAgentAvailable boolean [expr {[dict get $row userAgent] ne ""}] userAgentSource string $uaSource userAgentMayBeTruncated boolean $uaTruncated lappend fields $i object $item incr i incr matched } } finally { $db close } return [list {} object [list available boolean true scope string sampled-warning-requests requested number [llength $samples] matched number $matched missing number $missing ambiguous number $ambiguous records array $fields limitations string {Bounded examples, not aggregate bot attribution. Exact connection identifier and start time within 60 seconds before to 1 second after the warning are required. Cache lag, eviction, long requests, legacy rows without User-Agent, and absent identifiers can prevent matches. No raw access-log scan or cache refresh was performed. Multiple candidates are not attributed. Pool and User-Agent alone do not prove bot or human identity. No peer addresses are returned.}]]XQL Not present: Generic, PostgreSQL, Oracle
![[i]](/resources/acs-subsite/ZoomIn16.gif)