mirror of
https://gitee.com/XM-GO/PandaX.git
synced 2026-04-25 03:48:35 +08:00
【修改】k8s 配置
This commit is contained in:
252
apps/devops/services/k8s/logs/logs.go
Normal file
252
apps/devops/services/k8s/logs/logs.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LineIndexNotFound is returned if requested line could not be found
|
||||
var LineIndexNotFound = -1
|
||||
|
||||
// DefaultDisplayNumLogLines returns default number of lines in case of invalid request.
|
||||
var DefaultDisplayNumLogLines = 100
|
||||
|
||||
// MaxLogLines is a number that will be certainly bigger than any number of logs. Here 2 billion logs is certainly much larger
|
||||
// number of log lines than we can handle.
|
||||
var MaxLogLines int = 2000000000
|
||||
|
||||
const (
|
||||
NewestTimestamp = "newest"
|
||||
OldestTimestamp = "oldest"
|
||||
)
|
||||
|
||||
// Load logs from the beginning or the end of the log file.
|
||||
// This matters only if the log file is too large to be loaded completely.
|
||||
const (
|
||||
Beginning = "beginning"
|
||||
End = "end"
|
||||
)
|
||||
|
||||
// NewestLogLineId is the reference Id of the newest line.
|
||||
var NewestLogLineId = LogLineId{
|
||||
LogTimestamp: NewestTimestamp,
|
||||
}
|
||||
|
||||
// OldestLogLineId is the reference Id of the oldest line.
|
||||
var OldestLogLineId = LogLineId{
|
||||
LogTimestamp: OldestTimestamp,
|
||||
}
|
||||
|
||||
// DefaultSelection loads default log view selector that is used in case of invalid request
|
||||
// Downloads newest DefaultDisplayNumLogLines lines.
|
||||
var DefaultSelection = &Selection{
|
||||
OffsetFrom: 1 - DefaultDisplayNumLogLines,
|
||||
OffsetTo: 1,
|
||||
ReferencePoint: NewestLogLineId,
|
||||
LogFilePosition: End,
|
||||
}
|
||||
|
||||
// AllSelection returns all logs.
|
||||
var AllSelection = &Selection{
|
||||
OffsetFrom: -MaxLogLines,
|
||||
OffsetTo: MaxLogLines,
|
||||
ReferencePoint: NewestLogLineId,
|
||||
}
|
||||
|
||||
// LogDetails returns representation of log lines
|
||||
type LogDetails struct {
|
||||
|
||||
// Additional information of the logs e.g. container name, dates,...
|
||||
Info LogInfo `json:"info"`
|
||||
|
||||
// Reference point to keep track of the position of all the logs
|
||||
Selection `json:"selection"`
|
||||
|
||||
// Actual log lines of this page
|
||||
LogLines `json:"logs"`
|
||||
}
|
||||
|
||||
// LogInfo returns meta information about the selected log lines
|
||||
type LogInfo struct {
|
||||
|
||||
// Pod name.
|
||||
PodName string `json:"podName"`
|
||||
|
||||
// The name of the container the logs are for.
|
||||
ContainerName string `json:"containerName"`
|
||||
|
||||
// The name of the init container the logs are for.
|
||||
InitContainerName string `json:"initContainerName"`
|
||||
|
||||
// Date of the first log line
|
||||
FromDate LogTimestamp `json:"fromDate"`
|
||||
|
||||
// Date of the last log line
|
||||
ToDate LogTimestamp `json:"toDate"`
|
||||
|
||||
// Some log lines in the middle of the log file could not be loaded, because the log file is too large.
|
||||
Truncated bool `json:"truncated"`
|
||||
}
|
||||
|
||||
// Selection of a slice of logs.
|
||||
// It works just like normal slicing, but indices are referenced relatively to certain reference line.
|
||||
// So for example if reference line has index n and we want to download first 10 elements in array we have to use
|
||||
// from -n to -n+10. Setting ReferenceLogLineId the first line will result in standard slicing.
|
||||
type Selection struct {
|
||||
// ReferencePoint is the ID of a line which should serve as a reference point for this selector.
|
||||
// You can set it to last or first line if needed. Setting to the first line will result in standard slicing.
|
||||
ReferencePoint LogLineId `json:"referencePoint"`
|
||||
// First index of the slice relatively to the reference line(this one will be included).
|
||||
OffsetFrom int `json:"offsetFrom"`
|
||||
// Last index of the slice relatively to the reference line (this one will not be included).
|
||||
OffsetTo int `json:"offsetTo"`
|
||||
// The log file is loaded either from the beginning or from the end. This matters only if the log file is too
|
||||
// large to be handled and must be truncated (to avoid oom)
|
||||
LogFilePosition string `json:"logFilePosition"`
|
||||
}
|
||||
|
||||
// LogLineId uniquely identifies a line in logs - immune to log addition/deletion.
|
||||
type LogLineId struct {
|
||||
// timestamp of this line.
|
||||
LogTimestamp `json:"timestamp"`
|
||||
// in case of timestamp duplicates (rather unlikely) it gives the index of the duplicate.
|
||||
// For example if this LogTimestamp appears 3 times in the logs and the line is 1nd line with this timestamp,
|
||||
// then line num will be 1 or -3 (1st from beginning or 3rd from the end).
|
||||
// If timestamp is unique then it will be simply 1 or -1 (first from the beginning or first from the end, both mean the same).
|
||||
LineNum int `json:"lineNum"`
|
||||
}
|
||||
|
||||
// LogLines provides means of selecting log views. Problem with logs is that new logs are constantly added.
|
||||
// Therefore the number of logs constantly changes and we cannot use normal indexing. For example
|
||||
// if certain line has index N then it may not have index N anymore 1 second later as logs at the beginning of the list
|
||||
// are being deleted. Therefore it is necessary to reference log indices relative to some line that we are certain will not be deleted.
|
||||
// For example line in the middle of logs should have lifetime sufficiently long for the purposes of log visualisation. On average its lifetime
|
||||
// is equal to half of the log retention time. Therefore line in the middle of logs would serve as a good reference point.
|
||||
// LogLines allows to get ID of any line - this ID later allows to uniquely identify this line. Also it allows to get any
|
||||
// slice of logs relatively to certain reference line ID.
|
||||
type LogLines []LogLine
|
||||
|
||||
// LogLine is a single log line that split into timestamp and the actual content.
|
||||
type LogLine struct {
|
||||
Timestamp LogTimestamp `json:"timestamp"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// LogTimestamp is a timestamp that appears on the beginning of each log line.
|
||||
type LogTimestamp string
|
||||
|
||||
// SelectLogs returns selected part of LogLines as required by logSelector, moreover it returns IDs of first and last
|
||||
// of returned lines and the information of the resulting logView.
|
||||
func (self LogLines) SelectLogs(logSelection *Selection) (LogLines, LogTimestamp, LogTimestamp, Selection, bool) {
|
||||
requestedNumItems := logSelection.OffsetTo - logSelection.OffsetFrom
|
||||
referenceLineIndex := self.getLineIndex(&logSelection.ReferencePoint)
|
||||
if referenceLineIndex == LineIndexNotFound || requestedNumItems <= 0 || len(self) == 0 {
|
||||
// Requested reference line could not be found, probably it's already gone or requested no logs. Return no logs.
|
||||
return LogLines{}, "", "", Selection{}, false
|
||||
}
|
||||
fromIndex := referenceLineIndex + logSelection.OffsetFrom
|
||||
toIndex := referenceLineIndex + logSelection.OffsetTo
|
||||
lastPage := false
|
||||
if requestedNumItems > len(self) {
|
||||
fromIndex = 0
|
||||
toIndex = len(self)
|
||||
lastPage = true
|
||||
} else if toIndex > len(self) {
|
||||
fromIndex -= toIndex - len(self)
|
||||
toIndex = len(self)
|
||||
lastPage = logSelection.LogFilePosition == Beginning
|
||||
} else if fromIndex < 0 {
|
||||
toIndex += -fromIndex
|
||||
fromIndex = 0
|
||||
lastPage = logSelection.LogFilePosition == End
|
||||
}
|
||||
|
||||
// set the middle of log array as a reference point, this part of array should not be affected by log deletion/addition.
|
||||
newSelection := Selection{
|
||||
ReferencePoint: *self.createLogLineId(len(self) / 2),
|
||||
OffsetFrom: fromIndex - len(self)/2,
|
||||
OffsetTo: toIndex - len(self)/2,
|
||||
LogFilePosition: logSelection.LogFilePosition,
|
||||
}
|
||||
return self[fromIndex:toIndex], self[fromIndex].Timestamp, self[toIndex-1].Timestamp, newSelection, lastPage
|
||||
}
|
||||
|
||||
// getLineIndex returns the index of the line (referenced from beginning of log array) with provided logLineId.
|
||||
func (self LogLines) getLineIndex(logLineId *LogLineId) int {
|
||||
if logLineId == nil || logLineId.LogTimestamp == NewestTimestamp || len(self) == 0 || logLineId.LogTimestamp == "" {
|
||||
// if no line id provided return index of last item.
|
||||
return len(self) - 1
|
||||
} else if logLineId.LogTimestamp == OldestTimestamp {
|
||||
return 0
|
||||
}
|
||||
logTimestamp := logLineId.LogTimestamp
|
||||
|
||||
matchingStartedAt := 0
|
||||
matchingStartedAt = sort.Search(len(self), func(i int) bool {
|
||||
return self[i].Timestamp >= logTimestamp
|
||||
})
|
||||
|
||||
linesMatched := 0
|
||||
if matchingStartedAt < len(self) && self[matchingStartedAt].Timestamp == logTimestamp { // match found
|
||||
for (matchingStartedAt+linesMatched) < len(self) && self[matchingStartedAt+linesMatched].Timestamp == logTimestamp {
|
||||
linesMatched += 1
|
||||
}
|
||||
}
|
||||
|
||||
var offset int
|
||||
if logLineId.LineNum < 0 {
|
||||
offset = linesMatched + logLineId.LineNum
|
||||
} else {
|
||||
offset = logLineId.LineNum - 1
|
||||
}
|
||||
if 0 <= offset && offset < linesMatched {
|
||||
return matchingStartedAt + offset
|
||||
}
|
||||
return LineIndexNotFound
|
||||
}
|
||||
|
||||
// createLogLineId returns ID of the line with provided lineIndex.
|
||||
func (self LogLines) createLogLineId(lineIndex int) *LogLineId {
|
||||
logTimestamp := self[lineIndex].Timestamp
|
||||
// determine whether to use negative or positive indexing
|
||||
// check whether last line has the same index as requested line. If so, we can only use positive referencing
|
||||
// as more lines may appear at the end.
|
||||
// negative referencing is preferred as higher indices disappear later.
|
||||
var step int
|
||||
if self[len(self)-1].Timestamp == logTimestamp {
|
||||
// use positive referencing
|
||||
step = 1
|
||||
} else {
|
||||
step = -1
|
||||
}
|
||||
offset := step
|
||||
for ; 0 <= lineIndex-offset && lineIndex-offset < len(self); offset += step {
|
||||
if self[lineIndex-offset].Timestamp != logTimestamp {
|
||||
break
|
||||
}
|
||||
}
|
||||
return &LogLineId{
|
||||
LogTimestamp: logTimestamp,
|
||||
LineNum: offset,
|
||||
}
|
||||
}
|
||||
|
||||
// ToLogLines converts rawLogs (string) to LogLines. Proper log lines start with a timestamp which is chopped off.
|
||||
// In error cases the server returns a message without a timestamp
|
||||
func ToLogLines(rawLogs string) LogLines {
|
||||
logLines := LogLines{}
|
||||
for _, line := range strings.Split(rawLogs, "\n") {
|
||||
if line != "" {
|
||||
startsWithDate := ('0' <= line[0] && line[0] <= '9') //2017-...
|
||||
idx := strings.Index(line, " ")
|
||||
if idx > 0 && startsWithDate {
|
||||
timestamp := LogTimestamp(line[0:idx])
|
||||
content := line[idx+1:]
|
||||
logLines = append(logLines, LogLine{Timestamp: timestamp, Content: content})
|
||||
} else {
|
||||
logLines = append(logLines, LogLine{Timestamp: LogTimestamp("0"), Content: line})
|
||||
}
|
||||
}
|
||||
}
|
||||
return logLines
|
||||
}
|
||||
Reference in New Issue
Block a user