-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Server side logs #31
Changes from 3 commits
ef3d66a
70b5976
c13a28c
3be51d6
b0b0f72
5fff861
b5e8c5e
7d2afc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package files | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/flanksource/flanksource-ui/apm-hub/api/logs" | ||
) | ||
|
||
type FileSearch struct { | ||
FilesBackend []logs.FileSearchBackend | ||
} | ||
|
||
func (t *FileSearch) Search(q *logs.SearchParams) (r logs.SearchResults, err error) { | ||
var res logs.SearchResults | ||
|
||
for _, b := range t.FilesBackend { | ||
if !matchQueryLabels(q.Labels, b.Labels) { | ||
continue | ||
} | ||
|
||
files, err := readFilesLines(b.Paths) | ||
if err != nil { | ||
return res, fmt.Errorf("readFilesLines(); %w", err) | ||
} | ||
|
||
for _, content := range files { | ||
res.Results = append(res.Results, content...) | ||
} | ||
} | ||
|
||
return res, nil | ||
} | ||
|
||
type logsPerFile map[string][]logs.Result | ||
|
||
// readFilesLines will take a list of file paths | ||
// and then return each lines of those files. | ||
func readFilesLines(paths []string) (logsPerFile, error) { | ||
fileContents := make(logsPerFile, len(paths)) | ||
for _, path := range paths { | ||
fInfo, err := os.Stat(path) | ||
if err != nil { | ||
return nil, fmt.Errorf("error get file stat. path=%s; %w", path, err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't be an error, just returning an empty result There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Modified this. On error, it'll continue reading other files |
||
} | ||
|
||
file, err := os.Open(path) | ||
if err != nil { | ||
return nil, fmt.Errorf("error opening file. path=%s; %w", path, err) | ||
} | ||
|
||
scanner := bufio.NewScanner(file) | ||
for scanner.Scan() { | ||
fileContents[path] = append(fileContents[path], logs.Result{ | ||
Time: fInfo.ModTime().Format(time.RFC3339), | ||
// Labels: , all the records will have the same labels. Is it necessary to add it here? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we should also add the filename |
||
Message: strings.TrimSpace(scanner.Text()), | ||
}) | ||
} | ||
} | ||
|
||
return fileContents, nil | ||
} | ||
|
||
func matchQueryLabels(want, have map[string]string) bool { | ||
for label, val := range want { | ||
if val != have[label] { | ||
return false | ||
} | ||
} | ||
|
||
return true | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//go:build integration | ||
|
||
package files_test | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"net/http" | ||
"net/http/httptest" | ||
"os" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/flanksource/flanksource-ui/apm-hub/api/logs" | ||
"github.com/flanksource/flanksource-ui/apm-hub/cmd" | ||
"github.com/flanksource/flanksource-ui/apm-hub/pkg" | ||
) | ||
|
||
func TestFileSearch(t *testing.T) { | ||
confPath := "../../samples/config-file.yaml" | ||
|
||
backend, err := pkg.ParseConfig(nil, confPath) | ||
if err != nil { | ||
t.Fatal("Fail to parse the config file", err) | ||
} | ||
logs.GlobalBackends = append(logs.GlobalBackends, backend...) | ||
|
||
sp := logs.SearchParams{ | ||
Labels: map[string]string{ | ||
"name": "acmehost", | ||
"type": "Nginx", | ||
}, | ||
} | ||
b, err := json.Marshal(sp) | ||
if err != nil { | ||
t.Fatal("Fail to marshal search param") | ||
} | ||
|
||
req := httptest.NewRequest(http.MethodPost, "/search", strings.NewReader(string(b))) | ||
req.Header.Add("Content-Type", "application/json") | ||
rec := httptest.NewRecorder() | ||
|
||
e := cmd.SetupServer(nil) | ||
e.ServeHTTP(rec, req) | ||
|
||
var res logs.SearchResults | ||
if err := json.NewDecoder(rec.Body).Decode(&res); err != nil { | ||
t.Fatal("Failed to decode the search result") | ||
} | ||
|
||
nginxLogFile, err := os.Open("../../samples/nginx-access.log") | ||
if err != nil { | ||
t.Fatal("Fail to read nginx log", err) | ||
} | ||
|
||
scanner := bufio.NewScanner(nginxLogFile) | ||
var lines []string | ||
for scanner.Scan() { | ||
lines = append(lines, scanner.Text()) | ||
} | ||
|
||
if len(res.Results) != len(lines) { | ||
t.Fatalf("Expected [%d] lines but got [%d]", len(lines), len(res.Results)) | ||
} | ||
|
||
for i := range res.Results { | ||
if res.Results[i].Message != lines[i] { | ||
t.Fatalf("Incorrect line [%d]. Expected %s got %s", i+1, lines[i], res.Results[i].Message) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
backends: | ||
- file: | ||
- labels: | ||
name: acmehost | ||
type: Nginx | ||
path: | ||
- nginx-access.log |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
127.0.0.1 - - [20/Jan/2023:10:15:30 +0000] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36" | ||
127.0.0.1 - - [20/Jan/2023:10:15:32 +0000] "GET /about.html HTTP/1.1" 200 754 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36" | ||
127.0.0.1 - - [20/Jan/2023:10:15:34 +0000] "GET /contact.html HTTP/1.1" 200 834 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add support for globs ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added support