feat: support clash premium's structured log stream (#735)
* feat: support clash premium's structured log stream New version of Clash for Windows uses `ws://external-controller/logs?token=&level=info&format=structured` to get real time log. When Clash Premium Core reveices `format=structured`, it returns a different form of JSON log entry. Supporting this feature will allow better Clash for Windows integration Signed-off-by: Misty <gyc990326@gmail.com>
This commit is contained in:
parent
5cb57ffdc3
commit
0932a9c83f
1 changed files with 36 additions and 5 deletions
|
@ -293,6 +293,16 @@ type Log struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Payload string `json:"payload"`
|
Payload string `json:"payload"`
|
||||||
}
|
}
|
||||||
|
type LogStructuredField struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
type LogStructured struct {
|
||||||
|
Time string `json:"time"`
|
||||||
|
Level string `json:"level"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Fields []LogStructuredField `json:"fields"`
|
||||||
|
}
|
||||||
|
|
||||||
func getLogs(w http.ResponseWriter, r *http.Request) {
|
func getLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
levelText := r.URL.Query().Get("level")
|
levelText := r.URL.Query().Get("level")
|
||||||
|
@ -300,6 +310,12 @@ func getLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
levelText = "info"
|
levelText = "info"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatText := r.URL.Query().Get("format")
|
||||||
|
isStructured := false
|
||||||
|
if formatText == "structured" {
|
||||||
|
isStructured = true
|
||||||
|
}
|
||||||
|
|
||||||
level, ok := log.LogLevelMapping[levelText]
|
level, ok := log.LogLevelMapping[levelText]
|
||||||
if !ok {
|
if !ok {
|
||||||
render.Status(r, http.StatusBadRequest)
|
render.Status(r, http.StatusBadRequest)
|
||||||
|
@ -342,12 +358,27 @@ func getLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
|
|
||||||
|
if !isStructured {
|
||||||
if err := json.NewEncoder(buf).Encode(Log{
|
if err := json.NewEncoder(buf).Encode(Log{
|
||||||
Type: logM.Type(),
|
Type: logM.Type(),
|
||||||
Payload: logM.Payload,
|
Payload: logM.Payload,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
newLevel := logM.Type()
|
||||||
|
if newLevel == "warning" {
|
||||||
|
newLevel = "warn"
|
||||||
|
}
|
||||||
|
if err := json.NewEncoder(buf).Encode(LogStructured{
|
||||||
|
Time: time.Now().Format(time.TimeOnly),
|
||||||
|
Level: newLevel,
|
||||||
|
Message: logM.Payload,
|
||||||
|
Fields: []LogStructuredField{},
|
||||||
|
}); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if wsConn == nil {
|
if wsConn == nil {
|
||||||
|
|
Loading…
Reference in a new issue