Skip to content

Commit ca24c86

Browse files
feat: use lumberjack for logs + performance optimizations (#119)
* feat: use file system to store logs * fix: minor changes * feat: add context for api response * feat: add request id context * feat: add response model * feat: add request context * feat: add esresponse context * feat: add profiling * fix: logs middleware * fix: logs for RS API * fix: minor changes * fix: log middleware read all * fix: minor changes * fix: concurrent write on map * fix: record 500 logs * feat: cache bcrypt * fix: map lock * fix: minor fixes * fix: minor fixes * minor changes * minor fix * feat: updates the search index template * adds a new delimiter analyzer * uses index_prefixes * uses index_phrases * remove profiling * fix: use sync map * fix: use sync map * fix: use sync map * remove save response method * use new map * fix: use pointer * fix: minor fixes * fix: response body in logs * fix: minor fixes * fix: minor fixes * Update plugins/logs/logs.go Co-authored-by: Siddharth Kothari <sids.aquarius@gmail.com> * fix: minor changes * fix: add order key so a user's own template has a higher priority * fix: add order key so a user's own template has a higher priority * experiment with context * pulic struct * fix * fix * fix: use ctx for response * fix: minor changes * fix: remove sync.Map * fix: add chan * fix: remove sync wait * fix: check for passwordExists condition only once short-circuiting in L->R with && and || operators is guaranteed in golang * fix: update template to index numeric types as keyword Co-authored-by: Siddharth Kothari <sids.aquarius@gmail.com>
1 parent 6a71578 commit ca24c86

15 files changed

Lines changed: 343 additions & 107 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ build
88
tags
99

1010
config
11+
log

config/manual.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ HTTPS_CERT=sample/server.crt
88
HTTPS_KEY=sample/server.key
99
JWT_ROLE_KEY=role
1010
SET_SNIFFING=false
11+
LOG_FILE_PATH=log/arc/es.json

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ require (
99
github.com/google/uuid v1.0.0
1010
github.com/gorilla/mux v1.7.1
1111
github.com/hashicorp/golang-lru v0.5.0 // indirect
12+
github.com/natefinch/lumberjack v2.0.1-0.20190411184413-94d9e492cc53+incompatible
1213
github.com/olivere/elastic v6.2.21+incompatible
1314
github.com/olivere/elastic/v7 v7.0.17
1415
github.com/openzipkin/zipkin-go v0.1.6 // indirect
16+
github.com/pkg/profile v1.5.0
1517
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect
1618
github.com/robfig/cron v1.1.0
1719
github.com/rogpeppe/go-internal v1.2.2 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
333333
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
334334
github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
335335
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
336+
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
337+
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
338+
github.com/natefinch/lumberjack v2.0.1-0.20190411184413-94d9e492cc53+incompatible h1:uf1v9aKCMoL0/6eNuB2uaV/oi91/EMGWvlEN27jWe7I=
339+
github.com/natefinch/lumberjack v2.0.1-0.20190411184413-94d9e492cc53+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
336340
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
337341
github.com/olivere/elastic v6.2.21+incompatible h1:QnTuofzxOCV5FrYLywjkMxOmOWhAeild1VXxKRksK9Y=
338342
github.com/olivere/elastic v6.2.21+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
@@ -354,6 +358,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
354358
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
355359
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
356360
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
361+
github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
362+
github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
357363
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
358364
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
359365
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=

model/queryid/queryid.go

Lines changed: 0 additions & 30 deletions
This file was deleted.

model/request/request.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package request
2+
3+
import (
4+
"context"
5+
)
6+
7+
type contextKey string
8+
9+
// CtxKey is a key against which api request will get stored in the context.
10+
const CtxKey = contextKey("request")
11+
12+
// NewContext returns a new context with the given request body.
13+
func NewContext(ctx context.Context, request interface{}) context.Context {
14+
return context.WithValue(ctx, CtxKey, request)
15+
}
16+
17+
// FromContext retrieves the api request body stored against the request.ctxKey from the context.
18+
func FromContext(ctx context.Context) (*interface{}, error) {
19+
ctxRequest := ctx.Value(CtxKey)
20+
return &ctxRequest, nil
21+
}

model/response/response.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package response
2+
3+
import (
4+
"context"
5+
"sync"
6+
7+
"github.com/appbaseio/arc/errors"
8+
)
9+
10+
type contextKey string
11+
12+
// CtxKey is a key against which api response will get stored in the context.
13+
const ctxKey = contextKey("response")
14+
15+
type Response struct {
16+
L *sync.RWMutex
17+
Command chan string // use to control the go routine executions
18+
Response map[string]interface{}
19+
}
20+
21+
// NewContext returns a new context with the given response body.
22+
func NewContext(ctx context.Context, response Response) context.Context {
23+
return context.WithValue(ctx, ctxKey, response)
24+
}
25+
26+
// FromContext retrieves the api response body stored against the response.ctxKey from the context.
27+
func FromContext(ctx context.Context) (*Response, error) {
28+
ctxResponse := ctx.Value(ctxKey)
29+
if ctxResponse == nil {
30+
return nil, errors.NewNotFoundInContextError("Response")
31+
}
32+
responseBody, ok := ctxResponse.(Response)
33+
if !ok {
34+
return nil, errors.NewInvalidCastError("responseBody", "Response")
35+
}
36+
return &responseBody, nil
37+
}

plugins/auth/middleware.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,14 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
161161
{
162162
// if the request is made to elasticsearch using user credentials, then the user has to be an admin
163163
reqUser := obj.(*user.User)
164-
if hasBasicAuth && bcrypt.CompareHashAndPassword([]byte(reqUser.Password), []byte(password)) != nil {
164+
// No need to validate if already validated before
165+
if hasBasicAuth && !IsPasswordExist(reqUser.Username, password) && bcrypt.CompareHashAndPassword([]byte(reqUser.Password), []byte(password)) != nil {
165166
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
166167
util.WriteBackError(w, "invalid password", http.StatusUnauthorized)
167168
return
168169
}
170+
// Save validated username to avoid the bcrypt comparison
171+
SavePassword(reqUser.Username, password)
169172

170173
if reqCategory.IsFromES() || reqCategory.IsFromRS() {
171174
authenticated = *reqUser.IsAdmin

plugins/auth/util.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package auth
2+
3+
import (
4+
"sync"
5+
)
6+
7+
// UserToPasswordCache represents a map of bcrypt validated users
8+
var UserToPasswordCache = make(map[string]interface{})
9+
10+
// CurrentProcessMutex to stop concurrent writes on map
11+
var CurrentProcessMutex = sync.RWMutex{}
12+
13+
// SavePassword saved the password in the cache
14+
func SavePassword(username string, password string) {
15+
CurrentProcessMutex.Lock()
16+
UserToPasswordCache[username] = password
17+
CurrentProcessMutex.Unlock()
18+
}
19+
20+
// ClearPassword clears the password in the cache
21+
func ClearPassword(username string) {
22+
CurrentProcessMutex.Lock()
23+
delete(UserToPasswordCache, username)
24+
CurrentProcessMutex.Unlock()
25+
}
26+
27+
// IsPasswordExist checks whether the password in the cache or not
28+
func IsPasswordExist(username string, password string) bool {
29+
CurrentProcessMutex.Lock()
30+
cachedPassword, ok := UserToPasswordCache[username]
31+
CurrentProcessMutex.Unlock()
32+
if !ok {
33+
return false
34+
}
35+
return cachedPassword == password
36+
}

plugins/elasticsearch/middleware.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,13 @@ func intercept(h http.HandlerFunc) http.HandlerFunc {
192192
modifiedBody := []byte(modifiedBodyString)
193193
req.Body = ioutil.NopCloser(bytes.NewReader(modifiedBody))
194194
} else {
195-
body, err := ioutil.ReadAll(req.Body)
195+
reqBody := make(map[string]interface{})
196+
err := json.NewDecoder(req.Body).Decode(&reqBody)
196197
if err != nil {
197198
log.Errorln(logTag, ":", err)
198199
util.WriteBackError(w, err.Error(), http.StatusInternalServerError)
199200
return
200201
}
201-
d := json.NewDecoder(ioutil.NopCloser(bytes.NewReader(body)))
202-
reqBody := make(map[string]interface{})
203-
d.Decode(&reqBody)
204202
reqBody["_source"] = sources
205203
modifiedBody, _ := json.Marshal(reqBody)
206204
req.Body = ioutil.NopCloser(bytes.NewReader(modifiedBody))

0 commit comments

Comments
 (0)