Skip to content

Commit b1e8cca

Browse files
committed
- now if there is a perfect match on metaphone endpoint we return the result early
- now all log is exported to logs.txt and every 5 minutes exports data to the database
1 parent 5ff87a7 commit b1e8cca

File tree

5 files changed

+95
-85
lines changed

5 files changed

+95
-85
lines changed

controllers/controller.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,19 +197,36 @@ func GetName(c *gin.Context) {
197197

198198
//SearchSimilarNames search for all similar names by metaphone and Levenshtein method
199199
func SearchSimilarNames(c *gin.Context) {
200+
var metaphoneNames []models.NameType
201+
200202
//name to be searched
201203
name := c.Params.ByName("name")
202204
nameMetaphone := Metaphone.Pack(name)
203205

206+
//search perfect match
207+
database.Db.Raw("select * from name_types where name = ?", strings.ToUpper(name)).Find(&metaphoneNames)
208+
if len(metaphoneNames) == 1 {
209+
r := models.MetaphoneR{
210+
ID: metaphoneNames[0].ID,
211+
CreatedAt: metaphoneNames[0].CreatedAt,
212+
UpdatedAt: metaphoneNames[0].UpdatedAt,
213+
DeletedAt: metaphoneNames[0].DeletedAt,
214+
Name: metaphoneNames[0].Name,
215+
Classification: metaphoneNames[0].Classification,
216+
Metaphone: metaphoneNames[0].Metaphone,
217+
NameVariations: []string{metaphoneNames[0].NameVariations},
218+
}
219+
c.JSON(200, r)
220+
return
221+
}
222+
204223
//find all metaphoneNames matching metaphone
205-
var metaphoneNames []models.NameType
206224
database.Db.Raw("select * from name_types where metaphone = ?", nameMetaphone).Find(&metaphoneNames)
207225
similarNames := findNames(metaphoneNames, name, levenshtein)
208226

209227
//for recall purposes we can't only search for metaphone exact match's if no similar word is found
210-
preloadTable := c.MustGet("nameTypes").([]models.NameType)
211-
212228
if len(metaphoneNames) == 0 || len(similarNames) == 0 {
229+
preloadTable := c.MustGet("nameTypes").([]models.NameType)
213230
metaphoneNames = searchForAllSimilarMetaphone(nameMetaphone, preloadTable)
214231
similarNames = findNames(metaphoneNames, name, levenshtein)
215232

@@ -255,6 +272,7 @@ func SearchSimilarNames(c *gin.Context) {
255272
NameVariations: nameV,
256273
}
257274
c.JSON(200, r)
275+
return
258276
}
259277

260278
/*---------- used on SearchSimilarNames ----------*/

log/log.go

Lines changed: 52 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,81 @@
11
package log
22

33
import (
4-
"bytes"
4+
"bufio"
5+
"errors"
56
"fmt"
6-
database2 "github.com/Darklabel91/API_Names/database"
7+
"github.com/Darklabel91/API_Names/database"
78
"github.com/Darklabel91/API_Names/models"
8-
"github.com/gin-gonic/gin"
9-
"gorm.io/gorm"
10-
"io"
119
"os"
12-
"sync"
10+
"strings"
11+
"time"
1312
)
1413

15-
//user, err := c.Cookie("user")
16-
//if err != nil {
17-
// c.AbortWithStatus(http.StatusUnauthorized)
18-
// return
19-
//}
20-
21-
const logBufferSize = 1000
22-
23-
type databaseWriter struct {
24-
buffer bytes.Buffer
25-
db *gorm.DB
26-
mutex sync.Mutex
27-
logCount int
28-
}
29-
30-
func (w *databaseWriter) Write(p []byte) (n int, err error) {
31-
w.mutex.Lock()
32-
defer w.mutex.Unlock()
33-
34-
n, err = w.buffer.Write(p)
14+
func exportLog(filename string) error {
15+
//open the file
16+
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
3517
if err != nil {
36-
return
18+
return err
3719
}
20+
defer file.Close()
3821

39-
// Count the number of logs written to the buffer
40-
w.logCount += bytes.Count(p, []byte{'\n'})
22+
//create a scanner to read the file line by line
23+
scanner := bufio.NewScanner(file)
4124

42-
// If the buffer is full, flush it to the database
43-
if w.logCount >= logBufferSize {
44-
err = w.flush()
45-
if err != nil {
46-
return
47-
}
25+
// Loop through the lines
26+
var logs []models.Log
27+
for scanner.Scan() {
28+
line := scanner.Text()
29+
log, _ := logBreaker(line)
30+
logs = append(logs, log)
4831
}
4932

50-
return
51-
}
52-
53-
func (w *databaseWriter) flush() error {
54-
// Split the buffer into individual log messages
55-
logs := bytes.Split(w.buffer.Bytes(), []byte{'\n'})
56-
for _, log := range logs {
57-
// Skip empty log messages
58-
if len(log) == 0 {
59-
continue
60-
}
61-
62-
// Insert the log into the database
63-
err := w.db.Create(&models.Log{Message: string(log)}).Error
64-
if err != nil {
65-
return err
66-
}
33+
//check for any errors during scanning
34+
if err = scanner.Err(); err != nil {
35+
return err
6736
}
6837

69-
// Reset the buffer and log count
70-
w.buffer.Reset()
71-
w.logCount = 0
38+
//uploads to the database
39+
database.Db.Create(&logs)
7240

41+
// Return the line count and no error
7342
return nil
7443
}
7544

76-
func LocalLog() gin.HandlerFunc {
77-
// Create the file writer and database writer
78-
file, err := os.Create("log/gin.txt")
79-
if err != nil {
80-
fmt.Println("Log not created")
81-
return nil
45+
func logBreaker(message string) (models.Log, error) {
46+
stp1 := strings.Replace(message, "[GIN] ", "", -1)
47+
48+
stp2 := strings.Split(strings.TrimSpace(stp1), "|")
49+
if len(stp2) != 5 {
50+
fmt.Println("oi")
51+
return models.Log{}, errors.New("unexpected string length")
8252
}
83-
database := &databaseWriter{db: database2.InitDb()}
8453

85-
// Use a multi-writer to write to both the file and database writers
86-
writer := io.MultiWriter(file, database)
54+
stp3 := strings.Split(stp2[4], " ")
55+
if len(stp3) < 2 {
56+
return models.Log{}, errors.New("unexpected string length on second division")
57+
}
8758

88-
// Create the gin logger with the custom writer
89-
logger := gin.LoggerWithWriter(writer)
59+
return models.Log{
60+
Time: strings.TrimSpace(stp2[0]),
61+
Status: strings.TrimSpace(stp2[1]),
62+
Latency: strings.TrimSpace(stp2[2]),
63+
IP: strings.TrimSpace(stp2[3]),
64+
Method: strings.TrimSpace(stp3[1]),
65+
Path: strings.TrimSpace(stp3[len(stp3)-1]),
66+
}, nil
67+
}
9068

91-
return func(c *gin.Context) {
92-
// Call the logger middleware
93-
logger(c)
69+
func StartExportLog(filename string) {
70+
ticker := time.NewTicker(5 * time.Minute)
71+
defer ticker.Stop()
9472

95-
// Flush the logs to the database if necessary
96-
if database.logCount >= logBufferSize {
97-
err = database.flush()
73+
for {
74+
select {
75+
case <-ticker.C:
76+
err := exportLog(filename)
9877
if err != nil {
99-
fmt.Println(err)
100-
return
78+
fmt.Println("Error exporting log:", err)
10179
}
10280
}
10381
}

main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ package main
33
import (
44
"fmt"
55
"github.com/Darklabel91/API_Names/database"
6+
"github.com/Darklabel91/API_Names/log"
67
"github.com/Darklabel91/API_Names/routes"
78
)
89

10+
const FILENAME = "logs.txt"
11+
912
func main() {
1013
r := database.InitDb()
1114
if r == nil {
1215
return
1316
}
1417

1518
fmt.Println("- Listening and serving")
19+
go log.StartExportLog(FILENAME)
1620
routes.HandleRequests()
1721
}

models/modelsGrom.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ type User struct {
2121
}
2222

2323
//Log is the struct used to register the log file
24+
// Define a struct to hold the log data
2425
type Log struct {
2526
gorm.Model
26-
user string
27-
Message string
27+
Time string
28+
Status string
29+
Latency string
30+
IP string
31+
Method string
32+
Path string
2833
}

routes/routes.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,34 @@ package routes
33
import (
44
"github.com/Darklabel91/API_Names/controllers"
55
"github.com/Darklabel91/API_Names/database"
6-
"github.com/Darklabel91/API_Names/log"
76
"github.com/Darklabel91/API_Names/middleware"
87
"github.com/Darklabel91/API_Names/models"
98
"github.com/gin-gonic/gin"
9+
"os"
1010
"sync"
1111
)
1212

13-
const door = ":8080"
13+
const DOOR = ":8080"
14+
const FILENAME = "logs.txt"
1415

1516
var allowedIPs = []string{"127.0.0.1", "::1"} // List of allowed IP addresses
1617

1718
func HandleRequests() {
1819
gin.SetMode(gin.ReleaseMode)
1920
r := gin.Default()
20-
r.Use(log.LocalLog())
2121

2222
//use the OnlyAllowIPs middleware on all routes
2323
err := r.SetTrustedProxies(allowedIPs)
2424
if err != nil {
2525
return
2626
}
2727

28-
//export every log to a local file and upload to the database on every 1000k request's
29-
//r.Use(log.Testando)
28+
// Create a file to store the logs
29+
file, err := os.OpenFile(FILENAME, os.O_RDWR|os.O_CREATE, 0666)
30+
if err != nil {
31+
return
32+
}
33+
r.Use(gin.LoggerWithWriter(file))
3034

3135
//set up routes
3236
r.POST("/signup", controllers.Signup)
@@ -46,10 +50,11 @@ func HandleRequests() {
4650
gin.Logger()
4751

4852
// run
49-
err = r.Run(door)
53+
err = r.Run(DOOR)
5054
if err != nil {
5155
return
5256
}
57+
5358
}
5459

5560
//waitGroupMetaphone crates a waiting group for handling requests using controllers.SearchSimilarNames

0 commit comments

Comments
 (0)