Graphite: Improve functions endpoint (#111902)

Handle HTML response for functions endpoint

- If the endpoint starts with < return an error
- Update tests
- Catch error in FE and use default functions
This commit is contained in:
Andreas Christou
2025-10-01 20:04:34 +01:00
committed by GitHub
parent 0da9d49896
commit 4e2c3f19df
3 changed files with 39 additions and 7 deletions
+7 -1
View File
@@ -294,7 +294,13 @@ func (s *Service) handleFunctions(ctx context.Context, dsInfo *datasourceInfo, _
_, rawBody, statusCode, err := doGraphiteRequest[map[string]any](ctx, dsInfo, s.logger, req, true)
if err != nil {
return nil, statusCode, fmt.Errorf("version request failed: %v", err)
return nil, statusCode, fmt.Errorf("functions request failed: %v", err)
}
// It's possible that a HTML response may be returned
// This isn't valid so we'll return an error and use the default functions
if strings.HasPrefix(string(*rawBody), "<") {
return []byte{}, http.StatusNotAcceptable, fmt.Errorf("invalid functions response received from Graphite")
}
if rawBody == nil {
+23 -3
View File
@@ -735,21 +735,41 @@ func TestHandleFunctions(t *testing.T) {
responseBody: `{"error": "internal error"}`,
statusCode: 500,
expectError: true,
errorContains: "version request failed",
errorContains: "functions request failed",
},
{
name: "functions request not found",
responseBody: `{"error": "not found"}`,
statusCode: 404,
expectError: true,
errorContains: "version request failed",
errorContains: "functions request failed",
},
{
name: "network error",
responseBody: "",
statusCode: 0,
expectError: true,
errorContains: "version request failed",
errorContains: "functions request failed",
},
{
name: "html response",
responseBody: `<html>
<head>
<title>Graphite Browser</title>
</head>
<frameset rows="60,*" frameborder="1" border="1">
<frame src="/browser/header/" name="Header" id='header' scrolling="no" noresize="true" />
<frame src="/composer/?" name="content" id="composerFrame"/>
</frameset>
</html>
`,
statusCode: 200,
expectError: true,
errorContains: "invalid functions response received from Graphite",
},
}
@@ -1029,9 +1029,15 @@ export class GraphiteDatasource
};
if (config.featureToggles.graphiteBackendMode) {
const functions = await this.getResource<string>('functions');
this.funcDefs = gfunc.parseFuncDefs(functions);
return this.funcDefs;
try {
const functions = await this.getResource<string>('functions');
this.funcDefs = gfunc.parseFuncDefs(functions);
return this.funcDefs;
} catch (error) {
console.error('Fetching graphite functions error', error);
this.funcDefs = gfunc.getFuncDefs(this.graphiteVersion);
return this.funcDefs;
}
}
return lastValueFrom(