Class ::nsmcp::LogService
::nsmcp::LogService
create ... \
[ -analytics (default "") ] \
[ -authorizer:required authorizer:required ] \
[ -correlation:required correlation:required ] \
[ -lifetime:integer (default "900") ] \
[ -maxJobs:integer (default "128") ] \
[ -mutex mutex ] \
[ -peerRedactor:required peerRedactor:required ] \
[ -queue:required queue:required ] \
[ -redactor:required redactor:required ] \
[ -store:required store:required ]
Defined in /usr/local/ns/tcl/nsmcp/lib/log-tools.tclClass Relations
- class: ::nx::Class
![[i]](/resources/acs-subsite/ZoomIn16.gif)
- superclass: ::nx::Object
![[i]](/resources/acs-subsite/ZoomIn16.gif)
::nx::Class create ::nsmcp::LogService \
-superclass ::nx::Object
Methods (to be applied on instances)
poll (scripted, public)
<instance of nsmcp::LogService
> poll context handle
- Parameters:
- context (required)
- handle (required)
- Testcases:
-
No testcase defined.
:require $context
ns_mutex lock ${:mutex}
try {
if {![nsv_exists ${:store} $handle] || ![:owned $context [nsv_get ${:store} $handle]]} {
return -code error -errorcode {NSMCP RPC -32602} "Unknown or expired job handle"
}
set record [nsv_get ${:store} $handle]
if {[dict exists $record requiresPeers] && [dict get $record requiresPeers]} {${:authorizer} require $context diagnostics.logs.peers.read}
set data [list jobHandle string $handle status string [dict get $record status] server string [ns_info server]]
if {[dict get $record status] eq "complete"} {lappend data result object [dict get $record data]}
if {[dict get $record status] eq "failed"} {lappend data error string {Log search failed; consult the server log.}}
return [list {} object $data]
} finally {ns_mutex unlock ${:mutex}}results (scripted, public)
<instance of nsmcp::LogService
> results context handle cursor \
limit includePeers
- Parameters:
- context (required)
- handle (required)
- cursor (required)
- limit (required)
- includePeers (required)
- Testcases:
-
No testcase defined.
:require $context
if {$includePeers} {${:authorizer} require $context diagnostics.logs.peers.read}
set internal {}
ns_mutex lock ${:mutex}
try {
foreach key [nsv_array names ${:store}] {
set record [nsv_get ${:store} $key]
if {[:owned $context $record] && [dict exists $record mappings $handle]} {
set internal [dict get $record mappings $handle]; break
}
}
} finally {ns_mutex unlock ${:mutex}}
if {$internal eq ""} {
return -code error -errorcode {NSMCP RPC -32602} "Unknown or expired result handle"
}
set page [${:correlation} results $internal $cursor $limit]
set policy [expr {$includePeers ? ${:peerRedactor} : ${:redactor}}]
set page [$policy page $page]
set records {}; set index 0
foreach entry [dict get $page records] {
set fields {}
foreach key {timestamp processThread logThread severity requestIdentifier peerAddress method url protocol message pool timingSource} {
if {[dict exists $entry $key]} {lappend fields $key string [dict get $entry $key]}
}
foreach key {offset endOffset status responseBytes} {
set value [dict get $entry $key]
lappend fields $key [expr {$value eq "" ? "string" : "number"}] $value
}
foreach key {startTime acceptTime queueTime filterTime runTime} {
if {[dict exists $entry $key]} {lappend fields $key number [dict get $entry $key]}
}
foreach key {complete truncated orphanContinuation redacted} {lappend fields $key boolean [dict get $entry $key]}
lappend records $index object $fields
incr index
}
set data [list server string [ns_info server] resultHandle string $handle records array $records nextCursor string [dict get $page nextCursor]]
foreach key {resultCount generation} {lappend data $key number [dict get $page $key]}
foreach key {more scanIncomplete pending cacheFull} {lappend data $key boolean [dict get $page $key]}
return [list {} object $data]run (scripted, public)
<instance of nsmcp::LogService
> run handle operation identifier
- Parameters:
- handle (required)
- operation (required)
- identifier (required)
- Testcases:
-
No testcase defined.
ns_mutex lock ${:mutex}
try {
if {![nsv_exists ${:store} $handle]} return
set record [nsv_get ${:store} $handle]
dict set record status running
nsv_set ${:store} $handle $record
} finally {ns_mutex unlock ${:mutex}}
set mappings {}
try {
if {$operation eq "errors"} {
set data [:summary [${:correlation} errors] mappings]
} elseif {$operation eq "accessSummary"} {
if {${:analytics} eq ""} {error "access analytics is not configured"}
${:analytics} ingest [dict get $identifier from]
set data [::nsmcp::accessSummaryTriples [${:analytics} summary $identifier]]
} else {
set context [${:correlation} requestContext $identifier]
set data [list server string [ns_info server] requestIdentifier string $identifier system object [:summary [dict get $context system] mappings]]
set access {}; set index 0
dict for {source snapshot} [dict get $context access] {
lappend access $index object [:summary $snapshot mappings]
incr index
}
lappend data access array $access
}
dict set record status complete
dict set record data $data
dict set record mappings $mappings
} on error {message options} {
dict set record status failed
ns_log error "nsmcp: background log operation failed: $message"
}
ns_mutex lock ${:mutex}
try {nsv_set ${:store} $handle $record} finally {ns_mutex unlock ${:mutex}}start (scripted, public)
<instance of nsmcp::LogService
> start context operation \
[ identifier ]
- Parameters:
- context (required)
- operation (required)
- identifier (optional)
- Testcases:
-
No testcase defined.
:require $context
if {$operation ni {errors requestContext accessSummary}} {error "invalid log operation"}
if {$operation eq "requestContext" && ![::nsmcp::logRecordParser validRequestIdentifier $identifier]} {
return -code error -errorcode {NSMCP RPC -32602} "Invalid request identifier"
}
set requiresPeers [expr {$operation eq "accessSummary" &&
([dict exists $identifier peer] || ([dict exists $identifier includePeerAddresses] && [dict get $identifier includePeerAddresses]))}]
if {$requiresPeers} {${:authorizer} require $context diagnostics.logs.peers.read}
ns_mutex lock ${:mutex}
try {
foreach key [nsv_array names ${:store}] {
set record [nsv_get ${:store} $key]
if {[dict get $record expires] <= [clock seconds] && [dict get $record status] in {complete failed}} {
nsv_unset ${:store} $key
}
}
if {[llength [nsv_array names ${:store}]] >= ${:maxJobs}} {error "log job limit reached"}
set handle [ns_crypto::randombytes -encoding hex 32]
nsv_set ${:store} $handle [dict create principal [$context principal] server [$context server] expires [expr {[clock seconds]+${:lifetime}}] status queued mappings {} requiresPeers $requiresPeers]
try {
ns_job queue -detached ${:queue} [list [self] run $handle $operation $identifier]
} on error {message options} {
nsv_unset ${:store} $handle
return -options $options $message
}
} finally {ns_mutex unlock ${:mutex}}
return [list {} object [list jobHandle string $handle status string queued server string [ns_info server]]]