Class ::nsmcp::LogErrorSummaryTool (public)

 ::nx::Class ::nsmcp::LogErrorSummaryTool[i]

Defined in /usr/local/ns/tcl/nsmcp/log-summary.tcl

Testcases:
No testcase defined.
Source code:
    :property service:required
    :property {name log_error_summary}
    :property {permission diagnostics.logs.read}
    :property {description {Summarize selected system-log severities in a time window. Optional literal selects a case-sensitive message across the full requested window without a record-example cap and enables urlAggregation before detailed grouping limits. This returns queryless logged paths, counts, methods, authentication states, times and one representative request identifier per returned path. Up to 4096 paths are counted and maxGroups ranks at most 50; inspect unknownUrlRecords, capacityOmittedRecords, rankedOmittedRecords, scanComplete and literalSelection unknown-match counters separately. No response status is inferred from warning text. Correlate a few representative identifiers only for missing details. Current-log retention/rotation limitations still apply; defaults to Error, Fatal and Bug. Set severities to ["Warning"] for warning analysis or combine Warning with Error/Fatal/Bug. Severity labels are logging classifications, not an independent incident assessment. Combines duplicate-parameter warnings with bounded parameterCounts, normalizes scheduler lateness with timing aggregates and trailing suppression annotations, counts heuristic familyTotals for every selected record and bounded otherBreakdown source counts, reports exact overflowFamilyTotals and bounded redacted hash-priority overflowExamples/overflowSamplesByFamily across the scan with byte offsets, and ranks up to 512 counted groups before the output limit, and distinguishes ungroupedRecords from omittedGroupRecords. Reports physical repeat markers and suppressed-occurrence accounting without assigning suppressed events to the marker window. duplicateParameterOrigins aggregates authentication and redacted User-Agent counts overall and per parameter across all matching records before grouping limits, with explicit unknown, cardinality-overflow, ranked-omission and truncation counts. Samples expose direct authenticationState/authenticationSource without user IDs. Completed duplicate groups can include bounded, address-free access-cache correlation; missing evidence and User-Agents are unknown, not proof of human or bot activity. Returns grouped counts, first/last occurrence, redacted examples and coverage. Prefer this for daily error summaries instead of paging all log_errors records. Defaults to today in UTC; period today/yesterday may use an explicit timezone, or use lastMinutes or from/to (exclusive end). Current log only; rotations are not examined. coverage.logBounds reports first/last file-order and earliest/latest observed epoch timestamps and offsets across all timestamped severities, not just matching errors. coverage.rotation distinguishes configured signal/filename settings from unknown schedule and last verified rotation time. Observed bounds never certify complete window coverage. Returns explicit severityTotals independently of maxGroups. coverage.unrecognizedRecords counts unrecognized system-log entries; coverage.unrecognizedExamples provides up to five redacted examples with byte offsets. Expected ns:sched unlock/hold traces are omitted. Other stderr mutex traces have coverage.mutexTraceRecords and mutexTraceGroups with counts, minimum/maximum/mean seconds, offsets and maximum-duration thread; mutexTraceUngroupedRecords accounts for the 128-group bound. These groups aggregate all scanned traces, not just the five untimestampedExamples. Do not infer a file-wide distribution from examples or call a duration proof of contention. Short startup entries are reported separately via shortLogRecords. Recognizes PostgreSQL diagnostics with grouped DETAIL/HINT/CONTEXT via postgresRecords and postgresExamples. Neighboring timestamps are explicitly labeled inferred-neighbors; they are contextual bounds, not guaranteed event times. These diagnostic counters cover the scanned file; inferred times never enter window totals. Mutex traces are not errors; untimestamped Error/Fatal/Bug entries are reported as unknownTimeErrors rather than included in window totals. Scans the current file in resumable chunks with fixed bounds; running jobs report progress.examinedBytes and progress.sourceBytes. Runs asynchronously: poll log_results with jobHandle until complete; the completed result is the summary and has no record pages. Grouping is heuristic and bounded; report ungroupedRecords and coverage limitations.}}
    :property {inputSchema {
        {
            "type": "object",
            "properties": {
                "period": {
                    "type": "string",
                    "enum": [
                        "today",
                        "yesterday"
                    ]
                },
                "timezone": {
                    "type": "string"
                },
                "lastMinutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10080
                },
                "from": {
                    "type": "integer",
                    "minimum": 0
                },
                "to": {
                    "type": "integer",
                    "minimum": 1
                },
                "literal": {
                    "type": "string", "minLength": 1, "maxLength": 1024,
                    "description": "Case-sensitive literal in retained logical records, including continuations; up to 1024 UTF-8 bytes without CR/LF/NUL. Counts all matching records in the selected window and enables queryless URL aggregation, without an example-record cap."
                },
                "maxGroups": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50
                },
                "severities": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 4,
                    "uniqueItems": true,
                    "items": {
                        "type": "string",
                        "enum": [
                            "Warning",
                            "Error",
                            "Fatal",
                            "Bug"
                        ]
                    }
                }
            },
            "additionalProperties": false
        }
    }}

    :method options {arguments} {
        if {[lindex $arguments 1] ne "object"} {error "Expected an arguments object"}
        set values {timezone UTC maxGroups 20 severities {Error Fatal Bug}}
        set seen {}
        foreach {key type value} [lindex $arguments 2] {
            if {$key ni {period timezone lastMinutes from to maxGroups severities literal} || $key in $seen} {error "Unknown or duplicate summary argument"}
            lappend seen $key
            if {$key eq "literal"} {
                if {$type ne "string" || $value eq {} || [string length [encoding convertto utf-8 $value]]>1024
                    || [regexp {[\x00\r\n]} $value]} {error "literal must be a nonempty single-line string of at most 1024 UTF-8 bytes"}
                dict set values literal $value
                continue
            }
            if {$key eq "severities"} {
                if {$type ne "array" || [llength $value]%3 || [llength $value]<3 || [llength $value]>12} {error "Invalid severities array"}
                set selected {}
                foreach {index itemType severity} $value {
                    if {$itemType ne "string" || $severity ni {Warning Error Fatal Bug} || $severity in $selected} {error "Invalid or duplicate severity"}
                    lappend selected $severity
                }
                dict set values severities $selected
                continue
            }
            set expected [expr {$key in {period timezone} ? "string" : "number"}]
            if {$type ne $expected || ($type eq "number" && ![string is entier -strict $value])} {error "Invalid summary argument type"}
            dict set values $key $value
        }
        set timezone [dict get $values timezone]
        if {[string length $timezone]>128 || ![regexp {^[A-Za-z][A-Za-z0-9_+-]*(/[A-Za-z][A-Za-z0-9_+-]*)*$} $timezone] || [catch {clock format [clock seconds] -timezone $timezone}]} {error "Invalid timezone"}
        set selectors [expr {[dict exists $values period]+[dict exists $values lastMinutes]+([dict exists $values from] || [dict exists $values to])}]
        if {$selectors>1} {error "Use one time selector: period, lastMinutes or from/to"}
        set now [clock seconds]
        if {[dict exists $values from] || [dict exists $values to]} {
            if {![dict exists $values from] || ![dict exists $values to]} {error "Supply both from and to"}
        } elseif {[dict exists $values lastMinutes]} {
            set minutes [dict get $values lastMinutes]
            if {$minutes<1 || $minutes>10080} {error "lastMinutes must be 1..10080"}
            dict set values from [expr {$now-60*$minutes}]
            dict set values to $now
        } else {
            set period [expr {[dict exists $values period] ? [dict get $values period] : "today"}]
            if {$period ni {today yesterday}} {error "Invalid period"}
            set midnight [clock scan [clock format $now -timezone $timezone -format %Y-%m-%d] -timezone $timezone -format %Y-%m-%d]
            dict set values from [expr {$period eq "today" ? $midnight : [clock add $midnight -1 day -timezone $timezone]}]
            dict set values to [expr {$period eq "today" ? $now : $midnight}]
        }
        if {[dict get $values from]<0 || [dict get $values from]>=[dict get $values to]} {error "Expected 0 <= from < to"}
        if {[dict get $values maxGroups]<1 || [dict get $values maxGroups]>50} {error "maxGroups must be 1..50"}
        return $values
    }
    :public method validate {arguments} {
        if {[catch {:options $arguments} message]} {return -code error -errorcode {NSMCP RPC -32602} $message}
    }
    :public method execute {context arguments} {
        return [${:service} start $context errorSummary [:options $arguments]]
    }
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: