Skip to content

Commit d064bd1

Browse files
Merge pull request #41 from BrainNotFoundException/Lavnish/ElasticSearch
Lavnish/elastic search
2 parents 89b1c36 + 9465ace commit d064bd1

14 files changed

Lines changed: 380 additions & 19 deletions

File tree

.env.example

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,31 @@ JWT_SECRET=
33

44
FRONTEND_URL=http://localhost:3000
55

6-
POSTGRES_HOST=
7-
POSTGRES_PORT=
8-
POSTGRES_USER=abcd
9-
POSTGRES_PASSWORD=abcd
10-
POSTGRES_DB=abcd
6+
POSTGRES_HOST=postgres
7+
POSTGRES_PORT=5432
8+
POSTGRES_USER=devsoc
9+
POSTGRES_PASSWORD=devsoc
10+
POSTGRES_DB=devsoc
1111

1212
REDIS_HOST=
1313
REDIS_PORT=
1414
REDIS_PASSWORD=
1515

16+
ELASTIC_HOST=elasticsearch
17+
ELASTIC_PORT=9200
18+
ELASTIC_SCHEME=https
19+
ELASTIC_USERNAME=elastic
20+
ELASTIC_PASSWORD=gyattpass
21+
ELASTIC_INDEX=logs
22+
logger.level=ERROR #otherwise elastic search will keep yapping - i couldn't read shit b4 -- set to WARN if you wanna read sm not so imp stuff
23+
discovery.type=single-node #idk but sm sort of bootstrap issue
24+
25+
xpack.security.enabled=false
26+
27+
bootstrap.memory_lock=true
28+
ES_JAVA_OPTS=-Xms2g -Xmx2g #this is 4 sm memory related issues that might occur in docker fk elasticsearch
29+
# ts stands for -initial -max (heap sizes) and 2g signifies 2GB idk how much we'll actually need for logs but jus change that part as req ig
30+
1631
ENV=
1732

1833
GOOSE_MIGRATION_DIR=database/schema

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ dump.txt
3030
# Project build
3131
main
3232
*templ.go
33-
.DS_Store
33+
.DS_Store

cmd/api/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package main
22

33
import (
4+
"context"
45
"log"
56
"net/http"
67
"os"
78

9+
"github.com/CodeChefVIT/devsoc-backend-26/pkg/elastic"
810
"github.com/CodeChefVIT/devsoc-backend-26/pkg/middlewares"
911
"github.com/CodeChefVIT/devsoc-backend-26/pkg/redis"
1012
"github.com/CodeChefVIT/devsoc-backend-26/pkg/router"
@@ -15,6 +17,13 @@ import (
1517
func main() {
1618
utils.LoadConfig()
1719
utils.InitDB()
20+
elastic.InitElasticClient()
21+
22+
ctx := context.Background()
23+
24+
if err := elastic.CheckLogsIndex(ctx); err != nil {
25+
log.Fatal(err)
26+
}
1827
redis.InitRedis()
1928
redis.InitRequestManager()
2029

docker-compose.yml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
11
services:
2+
elasticsearch:
3+
image: docker.elastic.co/elasticsearch/elasticsearch:9.2.3
4+
container_name: elastic
5+
env_file:
6+
- .env
7+
ports:
8+
- 127.0.0.1:9200:9200
9+
volumes:
10+
- ./elasticsearch/certs:/usr/share/elasticsearch/config/certs:ro
11+
- elastic_data:/usr/share/elasticsearch/data
12+
ulimits:
13+
memlock:
14+
soft: -1
15+
hard: -1
16+
nofile:
17+
soft: 65536
18+
hard: 65536
19+
healthcheck:
20+
test:
21+
[
22+
"CMD-SHELL",
23+
"curl http://localhost:9200/_cluster/health || exit 1"
24+
]
25+
interval: 5s
26+
timeout: 2s
27+
retries: 20
28+
229
postgres:
330
image: postgres:16
431
container_name: devsoc_postgres
@@ -32,9 +59,14 @@ services:
3259
- GOFLAGS=-buildvcs=false
3360
restart: on-failure
3461
depends_on:
35-
- postgres
36-
- redis
62+
elasticsearch:
63+
condition: service_healthy
64+
postgres:
65+
condition: service_started
66+
redis:
67+
condition: service_started
3768

3869
volumes:
3970
postgres_data:
4071
redis_data:
72+
elastic_data:

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ require (
1818
github.com/cespare/xxhash/v2 v2.2.0 // indirect
1919
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
2020
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
21+
github.com/elastic/elastic-transport-go/v8 v8.8.0 // indirect
22+
github.com/elastic/go-elasticsearch/v9 v9.2.1 // indirect
2123
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
24+
github.com/go-logr/logr v1.4.2 // indirect
25+
github.com/go-logr/stdr v1.2.2 // indirect
2226
github.com/go-playground/locales v0.14.1 // indirect
2327
github.com/go-playground/universal-translator v0.18.1 // indirect
2428
github.com/goccy/go-json v0.10.3 // indirect
@@ -38,6 +42,10 @@ require (
3842
github.com/stretchr/testify v1.11.0 // indirect
3943
github.com/valyala/bytebufferpool v1.0.0 // indirect
4044
github.com/valyala/fasttemplate v1.2.2 // indirect
45+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
46+
go.opentelemetry.io/otel v1.35.0 // indirect
47+
go.opentelemetry.io/otel/metric v1.35.0 // indirect
48+
go.opentelemetry.io/otel/trace v1.35.0 // indirect
4149
golang.org/x/crypto v0.46.0 // indirect
4250
golang.org/x/net v0.47.0 // indirect
4351
golang.org/x/sync v0.19.0 // indirect

go.sum

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,17 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvw
1515
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
1616
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
1717
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
18+
github.com/elastic/elastic-transport-go/v8 v8.8.0 h1:7k1Ua+qluFr6p1jfJjGDl97ssJS/P7cHNInzfxgBQAo=
19+
github.com/elastic/elastic-transport-go/v8 v8.8.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
20+
github.com/elastic/go-elasticsearch/v9 v9.2.1 h1:/H8RKblXQbnVlFAkc0J5/FfSgVug60CU/DxlRcMdQf4=
21+
github.com/elastic/go-elasticsearch/v9 v9.2.1/go.mod h1:LvMSwNhRGZgkWWmErHS0IkT10wKzU+PRkOkQHGy3Wz0=
1822
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
1923
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
24+
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
25+
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
26+
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
27+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
28+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
2029
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
2130
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
2231
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -78,6 +87,14 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
7887
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
7988
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
8089
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
90+
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
91+
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
92+
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
93+
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
94+
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
95+
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
96+
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
97+
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
8198
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
8299
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
83100
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=

pkg/controllers/logs.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package controllers
33
import (
44
"encoding/json"
55
"net/http"
6-
"time"
76

87
"github.com/CodeChefVIT/devsoc-backend-26/pkg/db"
98
"github.com/CodeChefVIT/devsoc-backend-26/pkg/dto"
9+
"github.com/CodeChefVIT/devsoc-backend-26/pkg/elastic"
10+
"github.com/CodeChefVIT/devsoc-backend-26/pkg/models"
1011
"github.com/labstack/echo/v4"
1112
)
1213

@@ -33,19 +34,38 @@ func GetLogs(c echo.Context) error {
3334
createdBy = &s
3435
}
3536

36-
createdAt := ""
37-
if l.CreatedAt.Valid {
38-
createdAt = l.CreatedAt.Time.Format(time.RFC3339)
39-
}
40-
4137
resp = append(resp, dto.Log{
4238
ID: l.ID.String(),
4339
Type: l.Type,
4440
Body: body,
4541
CreatedBy: createdBy,
46-
CreatedAt: createdAt,
42+
CreatedAt: l.CreatedAt.Time,
4743
})
4844
}
4945

5046
return c.JSON(http.StatusOK, resp)
5147
}
48+
49+
func GetLog(c echo.Context) error {
50+
51+
query := c.QueryParam("q")
52+
53+
if query == "" {
54+
return c.JSON(http.StatusBadRequest, &models.Response{
55+
Status: "fail",
56+
Message: "The search query is required to search the logs!",
57+
})
58+
}
59+
60+
logs, err := elastic.SearchLogs(c.Request().Context(), query)
61+
62+
if err != nil {
63+
return c.JSON(http.StatusInternalServerError, &models.Response{
64+
Status: "fail",
65+
Message: err.Error(),
66+
})
67+
}
68+
69+
return c.JSON(http.StatusOK, logs)
70+
71+
}

pkg/dto/logs.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package dto
22

3+
import "time"
4+
35
type Log struct {
46
ID string `json:"id"`
57
Type string `json:"type"`
8+
Method string `json:"method"`
9+
URL string `json:"url"`
10+
IPAddress string `json:"ip_address"`
11+
UserAgent string `json:"user_agent"`
612
Body interface{} `json:"body"`
713
CreatedBy *string `json:"created_by"`
8-
CreatedAt string `json:"created_at"`
14+
CreatedAt time.Time `json:"created_at"`
915
}

pkg/elastic/client.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package elastic
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/CodeChefVIT/devsoc-backend-26/pkg/utils"
9+
es "github.com/elastic/go-elasticsearch/v9"
10+
)
11+
12+
var Client *es.Client
13+
14+
func InitElasticClient() {
15+
16+
cfg := utils.Config
17+
18+
elasticURL := fmt.Sprintf("%s://%s:%d", cfg.ElasticScheme, cfg.ElasticHost, cfg.ElasticPort)
19+
20+
esCfg := es.Config{
21+
Addresses: []string{elasticURL},
22+
MaxRetries: cfg.ElasticMaxRetries,
23+
RetryOnStatus: []int{502, 503, 504},
24+
RetryBackoff: func(i int) time.Duration {
25+
return time.Duration(i) * time.Second
26+
},
27+
}
28+
29+
client, err := es.NewClient(esCfg)
30+
if err != nil {
31+
panic(fmt.Sprintf("Failed to create ElasticSearch Client: %v", err))
32+
}
33+
34+
res, err := client.Info(client.Info.WithContext(context.Background()))
35+
if err != nil {
36+
panic(fmt.Sprintf("ElasticSearch Health Check Faileed: %v", err))
37+
}
38+
defer res.Body.Close()
39+
40+
fmt.Println("ElasticSearch Connected Successfully")
41+
Client = client
42+
}

pkg/elastic/index.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package elastic
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
9+
"github.com/CodeChefVIT/devsoc-backend-26/pkg/dto"
10+
)
11+
12+
const logsIndex = "logs"
13+
14+
func CheckLogsIndex(ctx context.Context) error {
15+
res, err := Client.Indices.Exists([]string{logsIndex})
16+
if err != nil {
17+
return err
18+
}
19+
20+
defer res.Body.Close()
21+
22+
if res.StatusCode == 200 {
23+
return nil
24+
}
25+
26+
mapping := map[string]interface{}{
27+
"mappings": map[string]interface{}{
28+
"properties": map[string]interface{}{
29+
"type": map[string]interface{}{
30+
"type": "keyword",
31+
},
32+
"method": map[string]interface{}{
33+
"type": "keyword",
34+
},
35+
"url": map[string]interface{}{
36+
"type": "text",
37+
},
38+
"ip_address": map[string]interface{}{
39+
"type": "ip",
40+
},
41+
"user_agent": map[string]interface{}{
42+
"type": "text",
43+
"fields": map[string]interface{}{
44+
"keyword": map[string]interface{}{
45+
"type": "keyword",
46+
},
47+
},
48+
},
49+
"created_by": map[string]interface{}{
50+
"type": "keyword",
51+
},
52+
"created_at": map[string]interface{}{
53+
"type": "date",
54+
},
55+
"body": map[string]interface{}{
56+
"type": "object",
57+
},
58+
},
59+
},
60+
}
61+
62+
body, _ := json.Marshal(mapping)
63+
64+
createRes, err := Client.Indices.Create(
65+
logsIndex,
66+
Client.Indices.Create.WithContext(ctx),
67+
Client.Indices.Create.WithBody(bytes.NewReader((body))),
68+
)
69+
70+
if err != nil {
71+
return err
72+
}
73+
74+
defer createRes.Body.Close()
75+
76+
if createRes.IsError() {
77+
return fmt.Errorf("Failed to create logs indexing for elastic client")
78+
}
79+
80+
return nil
81+
}
82+
83+
func IndexLog(ctx context.Context, log dto.Log) error {
84+
body, err := json.Marshal(log)
85+
if err != nil {
86+
return err
87+
}
88+
89+
res, err := Client.Index(
90+
logsIndex,
91+
bytes.NewReader(body),
92+
Client.Index.WithContext(ctx),
93+
)
94+
95+
if err != nil {
96+
return err
97+
}
98+
99+
defer res.Body.Close()
100+
101+
return nil
102+
}

0 commit comments

Comments
 (0)