Implemented the logging viewer
This commit is contained in:
parent
d925e85653
commit
71aa99a5e3
@ -259,6 +259,14 @@ p {
|
||||
.adminitemlog {
|
||||
padding-top: 14px;
|
||||
}
|
||||
.columns {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
.filterformcontainer {
|
||||
text-align: center;
|
||||
}
|
||||
@media (max-width: 991px) {
|
||||
.icons.oneback {
|
||||
margin-left: 113px;
|
||||
|
8
Admin/Scheme/LogEvent.go
Normal file
8
Admin/Scheme/LogEvent.go
Normal file
@ -0,0 +1,8 @@
|
||||
package Scheme
|
||||
|
||||
// Type for a log event
|
||||
type LogEvent struct {
|
||||
LogLine string
|
||||
LogLevel string // logwarn || logdebug || logerror || loginfo || logtalkative || logsecurity
|
||||
AB string // loga || logb
|
||||
}
|
73
Admin/Scheme/LoggingViewer.go
Normal file
73
Admin/Scheme/LoggingViewer.go
Normal file
@ -0,0 +1,73 @@
|
||||
package Scheme
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
)
|
||||
|
||||
// The type for the web logger viewer template
|
||||
type LoggingViewer struct {
|
||||
Title string
|
||||
SetLiveView bool
|
||||
CurrentLevel string
|
||||
CurrentTimeRange string
|
||||
CurrentCategory string
|
||||
CurrentImpact string
|
||||
CurrentSeverity string
|
||||
CurrentMessageName string
|
||||
CurrentSender string
|
||||
CurrentPage string
|
||||
MessageNames []MessageNames
|
||||
Sender []Sender
|
||||
Events []LogEvent
|
||||
}
|
||||
|
||||
// The type for the message names is necessary to be able to define a function on it.
|
||||
type MessageNames string
|
||||
|
||||
// The type for the senders is necessary to be able to define a function on it.
|
||||
type Sender string
|
||||
|
||||
// This function is used from the template to mark selected values. This is for the type MessageNames.
|
||||
func (lv MessageNames) IsSelected(field MessageNames, currentValue string) string {
|
||||
if string(field) == currentValue {
|
||||
return ` selected`
|
||||
} else {
|
||||
return ``
|
||||
}
|
||||
}
|
||||
|
||||
// This function is necessary to mark the HTML attribute as safe. Only then it is possible
|
||||
// to change plain HTML code.
|
||||
func (lv MessageNames) Safe(element string) template.HTMLAttr {
|
||||
return template.HTMLAttr(element)
|
||||
}
|
||||
|
||||
// This function is used from the template to mark selected values. This is for the type Sender.
|
||||
func (lv Sender) IsSelected(field Sender, currentValue string) string {
|
||||
if string(field) == currentValue {
|
||||
return ` selected`
|
||||
} else {
|
||||
return ``
|
||||
}
|
||||
}
|
||||
|
||||
// This function is necessary to mark the HTML attribute as safe. Only then it is possible
|
||||
// to change plain HTML code.
|
||||
func (lv Sender) Safe(element string) template.HTMLAttr {
|
||||
return template.HTMLAttr(element)
|
||||
}
|
||||
|
||||
// This function is used from the template to mark selected values.
|
||||
func (lv LoggingViewer) IsSelected(field, currentValue string) string {
|
||||
if field == currentValue {
|
||||
return ` selected`
|
||||
} else {
|
||||
return ``
|
||||
}
|
||||
}
|
||||
|
||||
// This function is necessary to mark the HTML attribute as safe. Only then it is possible
|
||||
// to change plain HTML code.
|
||||
func (lv LoggingViewer) Safe(element string) template.HTMLAttr {
|
||||
return template.HTMLAttr(element)
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package Scheme
|
||||
|
||||
// The type for the web logger viewer template
|
||||
type Viewer struct {
|
||||
Title string
|
||||
SetLiveView bool
|
||||
CurrentLevel string
|
||||
CurrentTimeRange string
|
||||
CurrentCategory string
|
||||
CurrentImpact string
|
||||
CurrentSeverity string
|
||||
CurrentMessageName string
|
||||
CurrentSender string
|
||||
CurrentPage string
|
||||
MessageNames []string
|
||||
Sender []string
|
||||
Events []LogEvent
|
||||
}
|
||||
|
||||
// Type for a log event
|
||||
type LogEvent struct {
|
||||
LogLine string
|
||||
LogLevel string // logwarn || logdebug || logerror || loginfo || logtalkative || logsecurity
|
||||
AB string // loga || logb
|
||||
}
|
@ -11,7 +11,7 @@ var LoggingViewer string = `
|
||||
<meta charset="utf-8">
|
||||
<title>{{.Title}}</title>
|
||||
{{if .SetLiveView}}
|
||||
<meta http-equiv="refresh" content="30; URL=/log?LiveView={{.SetLiveView}}">
|
||||
<meta http-equiv="refresh" content="30; URL=/log?Level={{.CurrentLevel}}&TimeRange={{.CurrentTimeRange}}&Category={{.CurrentCategory}}&Impact={{.CurrentImpact}}&Severity={{.CurrentSeverity}}&MSGName={{.CurrentMessageName}}&Sender={{.CurrentSender}}&CurrentPage={{.CurrentPage}}&LiveView={{.SetLiveView}}">
|
||||
{{end}}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="generator" content="Webflow">
|
||||
@ -24,12 +24,16 @@ var LoggingViewer string = `
|
||||
<div class="headercontainer">
|
||||
<h1>Logging Viewer</h1>
|
||||
</div>
|
||||
<div class="controlsection">
|
||||
<div class="w-section controlsection">
|
||||
<div class="w-row">
|
||||
<div class="w-col w-col-6">
|
||||
<h2 class="headercontrol">Options</h2>
|
||||
<div class="options">
|
||||
<a class="button optionbuttons" href="#">
|
||||
{{if .SetLiveView}}
|
||||
<a class="button optionbuttons currentoption" href="/log?Level={{.CurrentLevel}}&TimeRange={{.CurrentTimeRange}}&Category={{.CurrentCategory}}&Impact={{.CurrentImpact}}&Severity={{.CurrentSeverity}}&MSGName={{.CurrentMessageName}}&Sender={{.CurrentSender}}&CurrentPage={{.CurrentPage}}&LiveView=false">
|
||||
{{else}}
|
||||
<a class="button optionbuttons" href="/log?Level={{.CurrentLevel}}&TimeRange={{.CurrentTimeRange}}&Category={{.CurrentCategory}}&Impact={{.CurrentImpact}}&Severity={{.CurrentSeverity}}&MSGName={{.CurrentMessageName}}&Sender={{.CurrentSender}}&CurrentPage={{.CurrentPage}}&LiveView=true">
|
||||
{{end}}
|
||||
{{if .SetLiveView}}
|
||||
Disable live view
|
||||
{{else}}
|
||||
@ -41,74 +45,96 @@ var LoggingViewer string = `
|
||||
<div class="w-col w-col-6">
|
||||
<h2 class="headercontrol">Filtering</h2>
|
||||
<div class="filters">
|
||||
<div class="w-form">
|
||||
<form class="filterformcontainer" id="wf-form-Filters" name="wf-form-Filters" data-name="Filters">
|
||||
<div class="w-row">
|
||||
<div class="w-col w-col-6">
|
||||
<h3 class="subheader">By Time Range</h3><a class="button optionbuttons" href="#">Last 5 minutes</a><a class="button optionbuttons" href="#">Last 30 minutes</a><a class="button optionbuttons" href="#">Last 60 minutes</a><a class="button optionbuttons" href="#">Last 24 hours</a><a class="button optionbuttons" href="#">Last 7 days</a><a class="button optionbuttons" href="#">Last month</a><a class="button optionbuttons" href="#">All times</a>
|
||||
<div class="columns">
|
||||
<h3 class="subheader">By Time Range</h3>
|
||||
<label for="TimeRange">Time range:</label>
|
||||
<select class="w-select" id="TimeRange" name="TimeRange" data-name="TimeRange">
|
||||
<option value="*"{{.IsSelected "*" .CurrentTimeRange | .Safe}}>Whole time range</option>
|
||||
<option value="last5min"{{.IsSelected "last5min" .CurrentTimeRange | .Safe}}>Last 5 minutes</option>
|
||||
<option value="last30min"{{.IsSelected "last30min" .CurrentTimeRange | .Safe}}>Last 30 minutes</option>
|
||||
<option value="last60min"{{.IsSelected "last60min" .CurrentTimeRange | .Safe}}>Last 60 minutes</option>
|
||||
<option value="last24h"{{.IsSelected "last24h" .CurrentTimeRange | .Safe}}>Last 24 hours</option>
|
||||
<option value="last7d"{{.IsSelected "last7d" .CurrentTimeRange | .Safe}}>Last 7 days</option>
|
||||
<option value="lastMonth"{{.IsSelected "lastMonth" .CurrentTimeRange | .Safe}}>Last month</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-col w-col-6">
|
||||
<div class="columns">
|
||||
<h3 class="subheader">By Filter</h3>
|
||||
<div class="w-form">
|
||||
<form id="wf-form-Filters" name="wf-form-Filters" data-name="Filters">
|
||||
<label for="Level">Level:</label>
|
||||
<select class="w-select" id="Level" name="Level" data-name="Level">
|
||||
<option value="*">Any</option>
|
||||
<option value="INFO">Information</option>
|
||||
<option value="WARN">Warning</option>
|
||||
<option value="SECURITY">Security</option>
|
||||
<option value="ERROR">Error</option>
|
||||
<option value="DEBUG">Debug</option>
|
||||
<option value="TALKATIVE">Talkative</option>
|
||||
<option value="*"{{.IsSelected "*" .CurrentLevel | .Safe}}>Any</option>
|
||||
<option value="INFO"{{.IsSelected "INFO" .CurrentLevel | .Safe}}>Information</option>
|
||||
<option value="WARN"{{.IsSelected "WARN" .CurrentLevel | .Safe}}>Warning</option>
|
||||
<option value="SECURITY"{{.IsSelected "SECURITY" .CurrentLevel | .Safe}}>Security</option>
|
||||
<option value="ERROR"{{.IsSelected "ERROR" .CurrentLevel | .Safe}}>Error</option>
|
||||
<option value="DEBUG"{{.IsSelected "DEBUG" .CurrentLevel | .Safe}}>Debug</option>
|
||||
<option value="TALKATIVE"{{.IsSelected "TALKATIVE" .CurrentLevel | .Safe}}>Talkative</option>
|
||||
</select>
|
||||
<label for="Category">Category:</label>
|
||||
<select class="w-select" id="Category" name="Category" data-name="Category">
|
||||
<option value="*">Any</option>
|
||||
<option value="BUSINESS">Business</option>
|
||||
<option value="APP">Application</option>
|
||||
<option value="USER">User</option>
|
||||
<option value="SYSTEM">System</option>
|
||||
<option value="*"{{.IsSelected "*" .CurrentCategory | .Safe}}>Any</option>
|
||||
<option value="BUSINESS"{{.IsSelected "BUSINESS" .CurrentCategory | .Safe}}>Business</option>
|
||||
<option value="APP"{{.IsSelected "APP" .CurrentCategory | .Safe}}>Application</option>
|
||||
<option value="USER"{{.IsSelected "USER" .CurrentCategory | .Safe}}>User</option>
|
||||
<option value="SYSTEM"{{.IsSelected "SYSTEM" .CurrentCategory | .Safe}}>System</option>
|
||||
</select>
|
||||
<label for="Impact">Impact:</label>
|
||||
<select class="w-select" id="Impact" name="Impact" data-name="Impact">
|
||||
<option value="*">Any</option>
|
||||
<option value="LOW">Low</option>
|
||||
<option value="MIDDLE">Middle</option>
|
||||
<option value="HIGH">High</option>
|
||||
<option value="CRITICAL">Critical</option>
|
||||
<option value="UNKNOWN">Unknown</option>
|
||||
<option value="*"{{.IsSelected "*" .CurrentImpact | .Safe}}>Any</option>
|
||||
<option value="LOW"{{.IsSelected "LOW" .CurrentImpact | .Safe}}>Low</option>
|
||||
<option value="MIDDLE"{{.IsSelected "MIDDLE" .CurrentImpact | .Safe}}>Middle</option>
|
||||
<option value="HIGH"{{.IsSelected "HIGH" .CurrentImpact | .Safe}}>High</option>
|
||||
<option value="CRITICAL"{{.IsSelected "CRITICAL" .CurrentImpact | .Safe}}>Critical</option>
|
||||
<option value="UNKNOWN"{{.IsSelected "UNKNOWN" .CurrentImpact | .Safe}}>Unknown</option>
|
||||
</select>
|
||||
<label for="Severity">Severity:</label>
|
||||
<select class="w-select" id="Severity" name="Severity" data-name="Severity">
|
||||
<option value="*">Any</option>
|
||||
<option value="LOW">Low</option>
|
||||
<option value="MIDDLE">Middle</option>
|
||||
<option value="HIGH">High</option>
|
||||
<option value="CRITICAL">Critical</option>
|
||||
<option value="UNKNOWN">Unknown</option>
|
||||
<option value="*"{{.IsSelected "*" .CurrentSeverity | .Safe}}>Any</option>
|
||||
<option value="LOW"{{.IsSelected "LOW" .CurrentSeverity | .Safe}}>Low</option>
|
||||
<option value="MIDDLE"{{.IsSelected "MIDDLE" .CurrentSeverity | .Safe}}>Middle</option>
|
||||
<option value="HIGH"{{.IsSelected "HIGH" .CurrentSeverity | .Safe}}>High</option>
|
||||
<option value="CRITICAL"{{.IsSelected "CRITICAL" .CurrentSeverity | .Safe}}>Critical</option>
|
||||
<option value="UNKNOWN"{{.IsSelected "UNKNOWN" .CurrentSeverity | .Safe}}>Unknown</option>
|
||||
</select>
|
||||
<label for="MSGName">Message Names:</label>
|
||||
<select class="w-select" id="MSGName" name="MSGName" data-name="MSGName">
|
||||
<option value="*">Any</option>
|
||||
<option value="*"{{.IsSelected "*" .CurrentMessageName | .Safe}}>Any</option>
|
||||
{{$currentMessageName := .CurrentMessageName}}
|
||||
{{range .MessageNames}}
|
||||
<option value="{{.}}">{{.}}</option>
|
||||
<option value="{{.}}"{{.IsSelected . $currentMessageName | .Safe}}>{{.}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<label for="Sender">Sender:</label>
|
||||
<select class="w-select" id="Sender" name="Sender" data-name="Sender">
|
||||
<option value="*">Any</option>
|
||||
<option value="*"{{.IsSelected "*" .CurrentSender | .Safe}}>Any</option>
|
||||
{{$currentSender := .CurrentSender}}
|
||||
{{range .Sender}}
|
||||
<option value="{{.}}">{{.}}</option>
|
||||
<option value="{{.}}"{{.IsSelected . $currentSender | .Safe}}>{{.}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input class="w-button button optionbuttons applyfilters" type="submit" value="Apply filters" data-wait="Please wait...">
|
||||
</form>
|
||||
</div>
|
||||
<div class="w-form-done">
|
||||
<p>Thank you! Your submission has been received!</p>
|
||||
</div>
|
||||
<div class="w-form-fail">
|
||||
<p>Oops! Something went wrong while submitting the form :(</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="w-section">
|
||||
<h2 class="headeroutput">Output</h2>
|
||||
<ul class="loglist">
|
||||
{{range .Events}}
|
||||
@ -128,6 +154,12 @@ var LoggingViewer string = `
|
||||
<div class="w-hidden-main w-hidden-medium w-hidden-small newlineblock"></div>
|
||||
<input class="w-button button changepagebutton pagechangesubmit" type="submit" value="Change page" data-wait="Please wait...">
|
||||
</form>
|
||||
<div class="w-form-done">
|
||||
<p>Thank you! Your submission has been received!</p>
|
||||
</div>
|
||||
<div class="w-form-fail">
|
||||
<p>Oops! Something went wrong while submitting the form :(</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-hidden-main w-hidden-medium newlineblock"></div><a class="button changepagebutton" href="#">+1</a><a class="button changepagebutton" href="#">Last</a>
|
||||
</div>
|
||||
|
@ -1,9 +1,17 @@
|
||||
package DeviceDatabase
|
||||
|
||||
import (
|
||||
"github.com/SommerEngineering/Ocean/Admin/Scheme"
|
||||
)
|
||||
|
||||
// Read the message names out of the cache.
|
||||
func ReadMessageNames() (messageNames []string) {
|
||||
func ReadMessageNames() (messageNames []Scheme.MessageNames) {
|
||||
mutexCacheMessageNames.RLock()
|
||||
defer mutexCacheMessageNames.RUnlock()
|
||||
messageNames = cacheMessageNames
|
||||
|
||||
// Transform the values to the right format:
|
||||
for _, entry := range cacheMessageNames {
|
||||
messageNames = append(messageNames, Scheme.MessageNames(entry))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package DeviceDatabase
|
||||
|
||||
import (
|
||||
"github.com/SommerEngineering/Ocean/Admin/Scheme"
|
||||
"github.com/SommerEngineering/Ocean/Log"
|
||||
LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
@ -8,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// Read the message names from the database without any cache.
|
||||
func readMessageNamesFromDB() (result []string) {
|
||||
func readMessageNamesFromDB() (result []Scheme.MessageNames) {
|
||||
var nextMessageNames []string
|
||||
if err := logDBCollection.Find(bson.D{}).Distinct(`MessageName`, &nextMessageNames); err != nil {
|
||||
// Case: Error, was not able to write the event to the database:
|
||||
@ -18,6 +19,11 @@ func readMessageNamesFromDB() (result []string) {
|
||||
|
||||
// Sort the sender names:
|
||||
sort.Strings(nextMessageNames)
|
||||
result = nextMessageNames
|
||||
|
||||
// Transform the values to the right format:
|
||||
for _, entry := range nextMessageNames {
|
||||
result = append(result, Scheme.MessageNames(entry))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -1,9 +1,17 @@
|
||||
package DeviceDatabase
|
||||
|
||||
import (
|
||||
"github.com/SommerEngineering/Ocean/Admin/Scheme"
|
||||
)
|
||||
|
||||
// Read the sender names out of the cache.
|
||||
func ReadSenderNames() (senderNames []string) {
|
||||
func ReadSenderNames() (senderNames []Scheme.Sender) {
|
||||
mutexCacheSenderNames.RLock()
|
||||
defer mutexCacheSenderNames.RUnlock()
|
||||
senderNames = cacheSenderNames
|
||||
|
||||
// Transform the values to the right format:
|
||||
for _, entry := range cacheSenderNames {
|
||||
senderNames = append(senderNames, Scheme.Sender(entry))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package DeviceDatabase
|
||||
|
||||
import (
|
||||
"github.com/SommerEngineering/Ocean/Admin/Scheme"
|
||||
"github.com/SommerEngineering/Ocean/Log"
|
||||
LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
@ -8,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// Reads the sender names from the database without any caching.
|
||||
func readSenderNamesFromDB() (result []string) {
|
||||
func readSenderNamesFromDB() (result []Scheme.Sender) {
|
||||
var nextSenderNames []string
|
||||
if err := logDBCollection.Find(bson.D{}).Distinct(`Sender`, &nextSenderNames); err != nil {
|
||||
// Case: Was not possible to write to the database.
|
||||
@ -18,6 +19,10 @@ func readSenderNamesFromDB() (result []string) {
|
||||
|
||||
// Sort the sender names:
|
||||
sort.Strings(nextSenderNames)
|
||||
result = nextSenderNames
|
||||
|
||||
// Transform the values to the right format:
|
||||
for _, entry := range nextSenderNames {
|
||||
result = append(result, Scheme.Sender(entry))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package DeviceDatabase
|
||||
|
||||
import (
|
||||
"github.com/SommerEngineering/Ocean/Admin/Scheme"
|
||||
LM "github.com/SommerEngineering/Ocean/Log/Meta"
|
||||
"gopkg.in/mgo.v2"
|
||||
"sync"
|
||||
@ -16,8 +17,8 @@ var (
|
||||
cacheSizeNumberOfEvents int = 50
|
||||
cacheSizeTime2FlushSeconds int = 6
|
||||
nameCachesRefreshTimeSeconds int = 300
|
||||
cacheSenderNames []string = nil
|
||||
cacheMessageNames []string = nil
|
||||
cacheSenderNames []Scheme.Sender = nil
|
||||
cacheMessageNames []Scheme.MessageNames = nil
|
||||
logDB *mgo.Database = nil
|
||||
logDBSession *mgo.Session = nil
|
||||
logDBCollection *mgo.Collection = nil
|
||||
|
@ -26,20 +26,20 @@ func HandlerWebLog(response http.ResponseWriter, request *http.Request) {
|
||||
countParameters := len(request.Form)
|
||||
|
||||
// Setup the data for the HTML template:
|
||||
data := Scheme.Viewer{}
|
||||
data := Scheme.LoggingViewer{}
|
||||
data.Title = `Logging Viewer`
|
||||
data.Sender = DeviceDatabase.ReadSenderNames()
|
||||
data.MessageNames = DeviceDatabase.ReadMessageNames()
|
||||
|
||||
// To less parameters?
|
||||
if countParameters < 9 {
|
||||
// Initial view => refresh & first page (latest logs)
|
||||
// Initial view => first page (latest logs)
|
||||
data.Events = readLatest()
|
||||
data.SetLiveView = true
|
||||
} else {
|
||||
// Case: Custom view
|
||||
currentLevel := request.FormValue(`Level`)
|
||||
currentTimeRange := request.FormValue(`timeRange`)
|
||||
currentTimeRange := request.FormValue(`TimeRange`)
|
||||
currentCategory := request.FormValue(`Category`)
|
||||
currentImpact := request.FormValue(`Impact`)
|
||||
currentSeverity := request.FormValue(`Severity`)
|
||||
@ -96,6 +96,12 @@ func HandlerWebLog(response http.ResponseWriter, request *http.Request) {
|
||||
} else {
|
||||
data.CurrentSender = `*`
|
||||
}
|
||||
|
||||
if currentPage != `` {
|
||||
data.CurrentPage = currentPage
|
||||
} else {
|
||||
data.CurrentPage = `*`
|
||||
}
|
||||
}
|
||||
|
||||
// Write the MIME type and execute the template:
|
||||
|
Loading…
Reference in New Issue
Block a user