Skip to content

Commit

Permalink
Add Elasticsearch logger.
Browse files Browse the repository at this point in the history
  • Loading branch information
hscells committed Sep 18, 2018
1 parent 2d52d56 commit e04b064
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.log
*.log
go.sum
50 changes: 44 additions & 6 deletions cmd/bigbro/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,60 @@ package main

import (
"fmt"
"github.com/alexflint/go-arg"
"github.com/buger/goterm"
"github.com/gin-gonic/gin"
"github.com/hscells/bigbro"
"log"
"time"
)

type server struct {
l bigbro.Logger
}

type args struct {
Format string `help:"how events should be formatted and written" arg:"positional"`
Filename string `help:"filename to output logs to"`
Index string `help:"index for Elasticsearch to use"`
V string `help:"version for Elasticsearch event type"`
URL string `help:"URL for Elasticsearch"`
}

func (args) Version() string {
return "18.Sep.2018"
}

func (args) Description() string {
return "server for receiving and processing bigbro events"
}

func main() {
t := time.Now().Format(time.Stamp)
logger, err := bigbro.NewLogger(fmt.Sprintf("bigbrother_%s.log", t), bigbro.CSVFormatter{})
if err != nil {
log.Fatalln(err)
var (
args args
err error
logger bigbro.Logger
)
p := arg.MustParse(&args)
if args.Format == "elasticsearch" && args.V == "" && args.Index == "" {
p.Fail("you must provide one of --index and --v")
}
if args.Format == "csv" && args.Filename == "" {
p.Fail("you must provide one of --filename")
}

switch args.Format {
case "csv":
logger, err = bigbro.NewCSVLogger(args.Filename)
if err != nil {
log.Fatalln(err)
}
case "elasticsearch":
logger, err = bigbro.NewElasticsearchLogger(args.Index, args.V, args.URL)
if err != nil {
log.Fatalln(err)
}
default:
log.Fatalf("%s is not a valid log format\n", args.Format)
}

s := server{
Expand Down Expand Up @@ -60,7 +98,7 @@ func main() {
...is always watching
Harry Scells 2018
version 09.Aug.2018
version 18.Sep.2018
`)
}
g.Run("0.0.0.0:1984")
Expand Down
2 changes: 2 additions & 0 deletions cmd/bigbro/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ func wsEvent(ws *websocket.Conn, l bigbro.Logger) {
var event bigbro.Event
err := ws.ReadJSON(&event)
if err != nil {
log.Println(err)
return
}
err = l.Log(event)
if err != nil {
log.Println(err)
return
}
}
Expand Down
22 changes: 22 additions & 0 deletions csv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package bigbro

import (
"fmt"
"io"
)

// CSVFormatter is a formatter that formats in comma separated format.
type CSVFormatter struct {
w io.Writer
}

// Format in comma separated file.
func (l CSVFormatter) Format(e Event) string {
return fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%d,%d,%d,%d,%s\n", e.Time.String(), e.Actor, e.Method, e.Target, e.Name, e.ID, e.Location, e.X, e.Y, e.ScreenWidth, e.ScreenHeight, e.Comment)
}

// Write the csv line to file.
func (l CSVFormatter) Write(e Event) error {
_, err := l.w.Write([]byte(l.Format(e)))
return err
}
65 changes: 65 additions & 0 deletions elasticsearch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package bigbro

import (
"context"
"github.com/gin-gonic/gin/json"
"github.com/olivere/elastic"
"time"
)

// LogstashEvent is an event that is recognised by Elasticsearch.
type LogstashEvent struct {
Message string `json:"message"`
Version string `json:"@version"`
Timestamp time.Time `json:"@timestamp"`
Type string `json:"type"`
Host string `json:"host"`
Event Event `json:"event"`
}

// ElasticsearchFormatter is a log formatter that can output to Elasticsearch.
type ElasticsearchFormatter struct {
index string
version string
client *elastic.Client
}

func (f ElasticsearchFormatter) Format(e Event) string {
b, _ := json.Marshal(f.transformEvent(e))
return string(b)
}

func (f ElasticsearchFormatter) Write(e Event) error {
ctx := context.Background()
_, err := f.client.Index().
Index(f.index).
Type("event").
BodyJson(f.transformEvent(e)).
Do(ctx)
return err
}

// transformEvent returns an Elasticsearch compatible version of an Event.
func (f ElasticsearchFormatter) transformEvent(e Event) LogstashEvent {
return LogstashEvent{
Message: e.Name,
Version: f.version,
Timestamp: e.Time,
Type: e.Method,
Host: e.Location,
Event: e,
}
}

// NewElasticsearchFormatter creates a new formatter for Elasticsearch.
func NewElasticsearchFormatter(index, version, url string) (ElasticsearchFormatter, error) {
c, err := elastic.NewSimpleClient(elastic.SetURL(url))
if err != nil {
return ElasticsearchFormatter{}, err
}
return ElasticsearchFormatter{
index: index,
version: version,
client: c,
}, nil
}
13 changes: 2 additions & 11 deletions formatting.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
package bigbro

import "fmt"

// Formatter is a way of specifying how to format an event for logging.
type Formatter interface {
Format(e Event) string
}

// CSVFormatter is a formatter that formats in comma separated format.
type CSVFormatter struct{}

// Format in comma separated file.
func (l CSVFormatter) Format(e Event) string {
return fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%d,%d,%d,%d,%s\n", e.Time.String(), e.Actor, e.Method, e.Target, e.Name, e.ID, e.Location, e.X, e.Y, e.ScreenWidth, e.ScreenHeight, e.Comment)
}
Write(e Event) error
}
32 changes: 32 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module github.com/hscells/bigbro

require (
github.com/alexflint/go-arg v0.0.0-20180516182405-f7c0423bd11e
github.com/alexflint/go-scalar v0.0.0-20170216020425-e80c3b7ed292 // indirect
github.com/andybons/gogif v0.0.0-20140526152223-16d573594812
github.com/buger/goterm v0.0.0-20180423150900-6d19e6a8df12
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-heatmap v0.0.0-20180603032536-b89dbd73785a
github.com/fortytw2/leaktest v1.2.0 // indirect
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 // indirect
github.com/gin-gonic/gin v1.3.0
github.com/golang/protobuf v1.2.0 // indirect
github.com/gorilla/websocket v1.4.0
github.com/json-iterator/go v1.1.5 // indirect
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/olivere/elastic v6.1.25+incompatible
github.com/pkg/errors v0.8.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2 // indirect
github.com/ugorji/go/codec v0.0.0-20180831062425-e253f1f20942 // indirect
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3 // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
gopkg.in/yaml.v2 v2.2.1 // indirect
)
19 changes: 12 additions & 7 deletions js/bigbro.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ let BigBro = {
}

this.ws = new WebSocket(protocol + this.data.server + "/event");

let self = this;
for (let i = 0; i < this.data.events.length; i++) {
window.addEventListener(this.data.events[i], function (e) {
self.log(e, self.data.events[i]);
})
}
this.ws.onopen = function () {
for (let i = 0; i < self.data.events.length; i++) {
window.addEventListener(self.data.events[i], function (e) {
self.log(e, self.data.events[i]);
})
}
};
return this
},
// log logs an event with a specified method name (normally the actual event name).
log: function (e, method) {
log: function (e, method, comment) {
let event = {
target: e.target.tagName,
name: e.target.name,
Expand All @@ -57,6 +59,9 @@ let BigBro = {
// Strength of the wheel rotation.
event.comment = e.deltaY.toString();
}
if (comment != null) {
event.comment = comment;
}
this.ws.send(JSON.stringify(event));
}
};
26 changes: 18 additions & 8 deletions logging.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package bigbro

import (
"io"
"os"
"time"
)
Expand Down Expand Up @@ -36,27 +35,38 @@ type Event struct {

// Logger is the way in which logs are written to a file.
type Logger struct {
f io.Writer
formatter Formatter
}

// NewLogger creates a new logger.
func NewLogger(name string, formatter Formatter) (Logger, error) {
// NewCSVLogger creates a new CSV logger.
func NewCSVLogger(name string) (Logger, error) {
lf, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return Logger{}, err
}
lf.Truncate(0)

formatter := CSVFormatter{
w: lf,
}

return Logger{
f: lf,
formatter: formatter,
}, nil
}

// NewElasticsearchLogger creates a new Elasticsearch logger.
func NewElasticsearchLogger(index, version, url string) (Logger, error) {
f, err := NewElasticsearchFormatter(index, version, url)
if err != nil {
return Logger{}, err
}
return Logger{
formatter: f,
}, nil
}

// Log writes an event to the log file using the specified formatter.
func (l Logger) Log(e Event) error {
line := l.formatter.Format(e)
_, err := l.f.Write([]byte(line))
return err
return l.formatter.Write(e)
}

0 comments on commit e04b064

Please sign in to comment.