forked from boyska/circolog
server-side filtering
circologctl filter lets you load filters on circologd
This commit is contained in:
parent
8735ad2c21
commit
14e97dd43e
4 changed files with 70 additions and 2 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ func init() {
|
||||||
//"set": setCmd,
|
//"set": setCmd,
|
||||||
//"get": getCmd,
|
//"get": getCmd,
|
||||||
"pause": pauseCmd,
|
"pause": pauseCmd,
|
||||||
|
"filter": filterCmd,
|
||||||
"reload": reloadCmd,
|
"reload": reloadCmd,
|
||||||
"restart": restartCmd,
|
"restart": restartCmd,
|
||||||
"help": helpCmd,
|
"help": helpCmd,
|
||||||
|
@ -40,6 +42,24 @@ func init() {
|
||||||
|
|
||||||
//func getCmd(ctlSock string, args []string) error {}
|
//func getCmd(ctlSock string, args []string) error {}
|
||||||
|
|
||||||
|
func filterCmd(args []string) error {
|
||||||
|
filter := strings.Join(args[1:], " ")
|
||||||
|
postBody := make(map[string][]string)
|
||||||
|
postBody["where"] = []string{filter}
|
||||||
|
if globalOpts.debug {
|
||||||
|
fmt.Println("[DEBUG] postBody:", postBody)
|
||||||
|
}
|
||||||
|
resp, err := ctl.PostForm("http://unix/filter", postBody)
|
||||||
|
if resp.StatusCode != 200 || globalOpts.verbose {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(string(bodyBytes))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
func pauseCmd(args []string) error {
|
func pauseCmd(args []string) error {
|
||||||
var dontChangeAgain time.Duration
|
var dontChangeAgain time.Duration
|
||||||
flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
|
flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
func setupHTTPCtl(hub circolog.Hub, verbose, debug bool) *mux.Router {
|
func setupHTTPCtl(hub circolog.Hub, verbose, debug bool) *mux.Router {
|
||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
m.HandleFunc("/pause/toggle", togglePause(hub, verbose, debug)).Methods("POST")
|
m.HandleFunc("/pause/toggle", togglePause(hub, verbose, debug)).Methods("POST")
|
||||||
|
m.HandleFunc("/filter", setFilter(hub, verbose, debug)).Methods("POST")
|
||||||
m.HandleFunc("/status", getStatus(hub, verbose, debug)).Methods("GET")
|
m.HandleFunc("/status", getStatus(hub, verbose, debug)).Methods("GET")
|
||||||
m.HandleFunc("/logs/clear", clearQueue(hub, verbose)).Methods("POST")
|
m.HandleFunc("/logs/clear", clearQueue(hub, verbose)).Methods("POST")
|
||||||
m.HandleFunc("/help", printHelp(verbose)).Methods("GET")
|
m.HandleFunc("/help", printHelp(verbose)).Methods("GET")
|
||||||
|
@ -71,6 +72,26 @@ func togglePause(hub circolog.Hub, verbose, debug bool) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setFilter(hub circolog.Hub, verbose, debug bool) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
r.ParseForm()
|
||||||
|
where := r.FormValue("where")
|
||||||
|
response := make(chan circolog.CommandResponse)
|
||||||
|
hub.Commands <- circolog.HubFullCommand{
|
||||||
|
Command: circolog.CommandNewFilter,
|
||||||
|
Response: response,
|
||||||
|
Parameters: map[string]interface{}{"where": where},
|
||||||
|
}
|
||||||
|
resp := <-response
|
||||||
|
if !resp.Value.(map[string]interface{})["success"].(bool) {
|
||||||
|
w.WriteHeader(400)
|
||||||
|
}
|
||||||
|
w.Header().Set("content-type", "application/json")
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
enc.Encode(resp.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func clearQueue(hub circolog.Hub, verbose bool) http.HandlerFunc {
|
func clearQueue(hub circolog.Hub, verbose bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
if verbose {
|
if verbose {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
type ExprValue struct {
|
type ExprValue struct {
|
||||||
Node expr.Node
|
Node expr.Node
|
||||||
|
Expression string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ExprValue) String() string {
|
func (e *ExprValue) String() string {
|
||||||
|
@ -22,15 +23,24 @@ func (e *ExprValue) String() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (e *ExprValue) Set(value string) error {
|
func (e *ExprValue) Set(value string) error {
|
||||||
|
if value == "" {
|
||||||
|
e.Node = nil
|
||||||
|
e.Expression = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ast, err := expr.ParseExpression(value)
|
ast, err := expr.ParseExpression(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
e.Node = ast
|
e.Node = ast
|
||||||
|
e.Expression = value
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ExprValue) Validate(line map[string]interface{}) bool {
|
func (e *ExprValue) Validate(line map[string]interface{}) bool {
|
||||||
|
if e.Node == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
context := datasource.NewContextSimpleNative(line)
|
context := datasource.NewContextSimpleNative(line)
|
||||||
val, ok := vm.Eval(context, e.Node)
|
val, ok := vm.Eval(context, e.Node)
|
||||||
if !ok || val == nil { // errors when evaluating
|
if !ok || val == nil { // errors when evaluating
|
||||||
|
|
19
hub.go
19
hub.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.lattuga.net/boyska/circolog/filtering"
|
||||||
"gopkg.in/mcuadros/go-syslog.v2/format"
|
"gopkg.in/mcuadros/go-syslog.v2/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ const (
|
||||||
CommandClear = iota
|
CommandClear = iota
|
||||||
CommandPauseToggle = iota
|
CommandPauseToggle = iota
|
||||||
CommandStatus = iota
|
CommandStatus = iota
|
||||||
|
CommandNewFilter = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
// An HubFullCommand is a Command, complete with arguments
|
// An HubFullCommand is a Command, complete with arguments
|
||||||
|
@ -102,6 +104,7 @@ func (h *Hub) register(cl Client) {
|
||||||
// Run is hub main loop; keeps everything going
|
// Run is hub main loop; keeps everything going
|
||||||
func (h *Hub) Run() {
|
func (h *Hub) Run() {
|
||||||
active := true
|
active := true
|
||||||
|
var filter filtering.ExprValue
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case cl := <-h.Register:
|
case cl := <-h.Register:
|
||||||
|
@ -113,7 +116,7 @@ func (h *Hub) Run() {
|
||||||
delete(h.clients, cl)
|
delete(h.clients, cl)
|
||||||
}
|
}
|
||||||
case msg := <-h.LogMessages:
|
case msg := <-h.LogMessages:
|
||||||
if active == true {
|
if active == true && filter.Validate(msg) {
|
||||||
h.circbuf.Value = msg
|
h.circbuf.Value = msg
|
||||||
h.circbuf = h.circbuf.Next()
|
h.circbuf = h.circbuf.Next()
|
||||||
for client := range h.clients {
|
for client := range h.clients {
|
||||||
|
@ -141,7 +144,21 @@ func (h *Hub) Run() {
|
||||||
cmd.Response <- CommandResponse{Value: map[string]interface{}{
|
cmd.Response <- CommandResponse{Value: map[string]interface{}{
|
||||||
"size": h.circbuf.Len(),
|
"size": h.circbuf.Len(),
|
||||||
"paused": !active,
|
"paused": !active,
|
||||||
|
"filter": filter.Expression,
|
||||||
}}
|
}}
|
||||||
|
case CommandNewFilter:
|
||||||
|
if err := filter.Set(cmd.Parameters["where"].(string)); err != nil {
|
||||||
|
cmd.Response <- CommandResponse{Value: map[string]interface{}{
|
||||||
|
"success": false,
|
||||||
|
"error": err.Error(),
|
||||||
|
}}
|
||||||
|
} else {
|
||||||
|
cmd.Response <- CommandResponse{Value: map[string]interface{}{
|
||||||
|
"success": true,
|
||||||
|
"error": "",
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue