Skip to content

Commit 6590b58

Browse files
authored
Merge pull request #171 from jpinsonneau/372
NETOBSERV-372 UI: Improve loki error messages
2 parents ca10012 + 4eff52c commit 6590b58

File tree

17 files changed

+422
-50
lines changed

17 files changed

+422
-50
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ push:
129129

130130
.PHONY: serve
131131
serve:
132-
./plugin-backend
132+
./plugin-backend --loglevel trace
133133

134134
.PHONY: serve-mock
135135
serve-mock:

pkg/handler/flows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func getFlows(cfg loki.Config, client httpclient.Caller, params url.Values) (*mo
159159
}
160160
code, err := fetchParallel(client, queries, merger)
161161
if err != nil {
162-
return nil, code, errors.New("Error while fetching flows from Loki: " + err.Error())
162+
return nil, code, err
163163
}
164164
} else {
165165
// else, run all at once
@@ -173,7 +173,7 @@ func getFlows(cfg loki.Config, client httpclient.Caller, params url.Values) (*mo
173173
query := qb.Build()
174174
code, err := fetchSingle(client, query, merger)
175175
if err != nil {
176-
return nil, code, errors.New("Error while fetching flows from Loki: " + err.Error())
176+
return nil, code, err
177177
}
178178
}
179179

pkg/handler/loki.go

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/sirupsen/logrus"
13+
"gopkg.in/yaml.v3"
1314

1415
"github.com/netobserv/network-observability-console-plugin/pkg/handler/lokiclientmock"
1516
"github.com/netobserv/network-observability-console-plugin/pkg/httpclient"
@@ -18,6 +19,11 @@ import (
1819
"github.com/netobserv/network-observability-console-plugin/pkg/model"
1920
)
2021

22+
type LokiError struct {
23+
DisplayMessage string
24+
Message string
25+
}
26+
2127
var hlog = logrus.WithField("module", "handler")
2228

2329
const (
@@ -52,15 +58,18 @@ func EncodeQuery(url string) string {
5258

5359
func getLokiError(resp []byte, code int) string {
5460
var f map[string]string
61+
if code == http.StatusBadRequest {
62+
return fmt.Sprintf("Loki message: %s", resp)
63+
}
5564
err := json.Unmarshal(resp, &f)
5665
if err != nil {
57-
return fmt.Sprintf("Unknown error from Loki - cannot unmarshal (code: %d resp: %s)", code, resp)
66+
return fmt.Sprintf("Unknown error from Loki\ncannot unmarshal\n%s", resp)
5867
}
5968
message, ok := f["message"]
6069
if !ok {
61-
return fmt.Sprintf("Unknown error from Loki - no message found (code: %d)", code)
70+
return "Unknown error from Loki\nno message found"
6271
}
63-
return fmt.Sprintf("Error from Loki (code: %d): %s", code, message)
72+
return fmt.Sprintf("Loki message: %s", message)
6473
}
6574

6675
func executeLokiQuery(flowsURL string, lokiClient httpclient.Caller) ([]byte, int, error) {
@@ -77,7 +86,7 @@ func executeLokiQuery(flowsURL string, lokiClient httpclient.Caller) ([]byte, in
7786
}
7887
if code != http.StatusOK {
7988
msg := getLokiError(resp, code)
80-
return nil, http.StatusBadRequest, errors.New("Loki backend responded: " + msg)
89+
return nil, http.StatusBadRequest, errors.New(msg)
8190
}
8291
code = http.StatusOK
8392
return resp, code, nil
@@ -154,3 +163,80 @@ func fetchParallel(lokiClient httpclient.Caller, queries []string, merger loki.M
154163
codeOut = http.StatusOK
155164
return codeOut, nil
156165
}
166+
167+
func LokiReady(cfg loki.Config) func(w http.ResponseWriter, r *http.Request) {
168+
lokiClient := newLokiClient(&cfg)
169+
170+
return func(w http.ResponseWriter, r *http.Request) {
171+
baseURL := strings.TrimRight(cfg.URL.String(), "/")
172+
173+
resp, code, err := executeLokiQuery(fmt.Sprintf("%s/%s", baseURL, "ready"), lokiClient)
174+
if err != nil {
175+
writeError(w, code, err.Error())
176+
return
177+
}
178+
179+
status := string(resp)
180+
if strings.Contains(status, "ready") {
181+
code = http.StatusOK
182+
writeText(w, code, resp)
183+
return
184+
}
185+
186+
writeError(w, code, fmt.Sprintf("Loki returned a non ready status: %s", status))
187+
}
188+
}
189+
190+
func LokiMetrics(cfg loki.Config) func(w http.ResponseWriter, r *http.Request) {
191+
lokiClient := newLokiClient(&cfg)
192+
193+
return func(w http.ResponseWriter, r *http.Request) {
194+
baseURL := strings.TrimRight(cfg.URL.String(), "/")
195+
196+
resp, code, err := executeLokiQuery(fmt.Sprintf("%s/%s", baseURL, "metrics"), lokiClient)
197+
if err != nil {
198+
writeError(w, code, err.Error())
199+
return
200+
}
201+
202+
writeText(w, code, resp)
203+
}
204+
}
205+
206+
func LokiBuildInfos(cfg loki.Config) func(w http.ResponseWriter, r *http.Request) {
207+
lokiClient := newLokiClient(&cfg)
208+
209+
return func(w http.ResponseWriter, r *http.Request) {
210+
baseURL := strings.TrimRight(cfg.URL.String(), "/")
211+
212+
resp, code, err := executeLokiQuery(fmt.Sprintf("%s/%s", baseURL, "loki/api/v1/status/buildinfo"), lokiClient)
213+
if err != nil {
214+
writeError(w, code, err.Error())
215+
return
216+
}
217+
218+
writeText(w, code, resp)
219+
}
220+
}
221+
222+
func LokiConfig(cfg loki.Config, param string) func(w http.ResponseWriter, r *http.Request) {
223+
lokiClient := newLokiClient(&cfg)
224+
225+
return func(w http.ResponseWriter, r *http.Request) {
226+
baseURL := strings.TrimRight(cfg.URL.String(), "/")
227+
228+
resp, code, err := executeLokiQuery(fmt.Sprintf("%s/%s", baseURL, "config"), lokiClient)
229+
if err != nil {
230+
writeError(w, code, err.Error())
231+
return
232+
}
233+
234+
cfg := make(map[string]interface{})
235+
err = yaml.Unmarshal(resp, &cfg)
236+
if err != nil {
237+
writeError(w, code, err.Error())
238+
return
239+
}
240+
writeJSON(w, code, cfg[param])
241+
}
242+
}

pkg/handler/response.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ import (
1111
"github.com/netobserv/network-observability-console-plugin/pkg/model"
1212
)
1313

14+
func writeText(w http.ResponseWriter, code int, bytes []byte) {
15+
w.Header().Set("Content-Type", "text/plain")
16+
w.WriteHeader(code)
17+
_, err := w.Write(bytes)
18+
if err != nil {
19+
hlog.Errorf("Error while responding Text: %v", err)
20+
}
21+
}
22+
1423
func writeJSON(w http.ResponseWriter, code int, payload interface{}) {
1524
response, err := json.Marshal(payload)
1625
if err != nil {

pkg/handler/topology.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func getTopologyFlows(cfg loki.Config, client httpclient.Caller, params url.Valu
7979
}
8080
code, err := fetchParallel(client, queries, merger)
8181
if err != nil {
82-
return nil, code, errors.New("Error while fetching flows from Loki: " + err.Error())
82+
return nil, code, err
8383
}
8484
} else {
8585
// else, run all at once
@@ -93,7 +93,7 @@ func getTopologyFlows(cfg loki.Config, client httpclient.Caller, params url.Valu
9393
}
9494
code, err = fetchSingle(client, query, merger)
9595
if err != nil {
96-
return nil, code, errors.New("Error while fetching flows from Loki: " + err.Error())
96+
return nil, code, err
9797
}
9898
}
9999

pkg/server/routes.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import (
1212
func setupRoutes(cfg *Config) *mux.Router {
1313
r := mux.NewRouter()
1414
r.HandleFunc("/api/status", handler.Status)
15+
r.HandleFunc("/api/loki/ready", handler.LokiReady(cfg.Loki))
16+
r.HandleFunc("/api/loki/metrics", handler.LokiMetrics(cfg.Loki))
17+
r.HandleFunc("/api/loki/buildinfo", handler.LokiBuildInfos(cfg.Loki))
18+
r.HandleFunc("/api/loki/config/limits", handler.LokiConfig(cfg.Loki, "limits_config"))
1519
r.HandleFunc("/api/loki/flows", handler.GetFlows(cfg.Loki))
1620
r.HandleFunc("/api/loki/export", handler.ExportFlows(cfg.Loki))
1721
r.HandleFunc("/api/loki/topology", handler.GetTopology(cfg.Loki))

web/locales/en/plugin__network-observability-plugin.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@
6262
"Filter already exists": "Filter already exists",
6363
"Clear all filters": "Clear all filters",
6464
"Edit filters": "Edit filters",
65+
"Build info": "Build info",
66+
"Configuration limits": "Configuration limits",
67+
"Metrics": "Metrics",
68+
"You may consider the following query changes to avoid this error": "You may consider the following query changes to avoid this error",
69+
"Reduce the Query Options -> limit to reduce the number of results": "Reduce the Query Options -> limit to reduce the number of results",
70+
"Increase Loki \"max_entries_limit_per_query\" entry in configuration file": "Increase Loki \"max_entries_limit_per_query\" entry in configuration file",
71+
"Add some filters like Namespace or Name to reduce the number of results": "Add some filters like Namespace or Name to reduce the number of results",
72+
"Reduce the time range to decrease the number of results": "Reduce the time range to decrease the number of results",
73+
"Increase Loki \"max_query_length\" entry in configuration file": "Increase Loki \"max_query_length\" entry in configuration file",
74+
"Configuring Grafana Loki": "Configuring Grafana Loki",
75+
"Show metrics": "Show metrics",
76+
"Show build info": "Show build info",
77+
"Show configuration limits": "Show configuration limits",
78+
"Copy": "Copy",
79+
"Copied": "Copied",
6580
"Manage columns": "Manage columns",
6681
"Selected columns will appear in the table.": "Selected columns will appear in the table.",
6782
"Click and drag the items to reorder the columns in the table.": "Click and drag the items to reorder the columns in the table.",
@@ -90,8 +105,6 @@
90105
"Filter on {{name}}": "Filter on {{name}}",
91106
"Flow Details": "Flow Details",
92107
"JSON": "JSON",
93-
"Copy": "Copy",
94-
"Copied": "Copied",
95108
"Kind not managed": "Kind not managed",
96109
"Unable to get flows": "Unable to get flows",
97110
"No results found": "No results found",

web/setup-tests.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,17 @@ jest.mock('react-router-dom', () => ({
8787
useHistory: () => ({
8888
push: jest.fn(),
8989
}),
90+
Link: () => {
91+
return null;
92+
}
9093
}));
9194

9295
//Mock routes
9396
jest.mock('./src/api/routes', () => ({
9497
getPods: jest.fn(async () => ['ABCD']),
9598
getNamespaces: jest.fn(async () => ['EFGH']),
96-
getConfig: jest.fn(async () => ({ portNaming: { enable: true, portNames: new Map() } }))
99+
getConfig: jest.fn(async () => ({ portNaming: { enable: true, portNames: new Map() } })),
100+
getLokiReady: jest.fn(async () => 'ready'),
97101
}));
98102

99103
global.console = {

web/src/api/routes.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,39 @@ export const getConfig = (): Promise<Config> => {
8484
};
8585
});
8686
};
87+
88+
export const getLokiReady = (): Promise<string> => {
89+
return axios.get(ContextSingleton.getHost() + '/api/loki/ready').then(r => {
90+
if (r.status >= 400) {
91+
throw new Error(`${r.statusText} [code=${r.status}]`);
92+
}
93+
return r.data;
94+
});
95+
};
96+
97+
export const getMetrics = (): Promise<string> => {
98+
return axios.get(ContextSingleton.getHost() + '/api/loki/metrics').then(r => {
99+
if (r.status >= 400) {
100+
throw new Error(`${r.statusText} [code=${r.status}]`);
101+
}
102+
return r.data;
103+
});
104+
};
105+
106+
export const getBuildInfo = (): Promise<unknown> => {
107+
return axios.get(ContextSingleton.getHost() + '/api/loki/buildinfo').then(r => {
108+
if (r.status >= 400) {
109+
throw new Error(`${r.statusText} [code=${r.status}]`);
110+
}
111+
return r.data;
112+
});
113+
};
114+
115+
export const getLimits = (): Promise<unknown> => {
116+
return axios.get(ContextSingleton.getHost() + '/api/loki/config/limits').then(r => {
117+
if (r.status >= 400) {
118+
throw new Error(`${r.statusText} [code=${r.status}]`);
119+
}
120+
return r.data;
121+
});
122+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#loki-error-container {
2+
overflow: auto;
3+
height: 100%;
4+
}
5+
6+
.error-text-content {
7+
display: flex;
8+
flex-direction: column;
9+
align-items: center;
10+
justify-content: center;
11+
}
12+
13+
.loki-error-icon,
14+
.loki-error-message {
15+
color: #A30000 !important;
16+
margin-bottom: 1em;
17+
}
18+
19+
.health-config-text,
20+
.error-text-content>p {
21+
margin-top: 1em !important;
22+
}
23+
24+
.error-text-content>blockquote {
25+
width: 50%;
26+
}

0 commit comments

Comments
 (0)