@@ -1301,6 +1301,123 @@ func TestDrilldown_DetectedFieldValues_IgnoreZeroHitNativeValues(t *testing.T) {
13011301 }
13021302}
13031303
1304+ func TestDrilldown_DetectedFields_ServesStaleCacheOnBackendError (t * testing.T ) {
1305+ vlBackend := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1306+ http .Error (w , "backend unavailable" , http .StatusBadGateway )
1307+ }))
1308+ defer vlBackend .Close ()
1309+
1310+ p := newGapTestProxy (t , vlBackend .URL )
1311+ cacheKey := "detected_fields::query=%7Bservice_name%3D%22cached-svc%22%7D"
1312+ p .setJSONCacheWithTTL (cacheKey , time .Millisecond , map [string ]interface {}{
1313+ "status" : "success" ,
1314+ "data" : []map [string ]interface {}{
1315+ {"label" : "cached_field" , "type" : "string" , "cardinality" : 1 },
1316+ },
1317+ "fields" : []map [string ]interface {}{
1318+ {"label" : "cached_field" , "type" : "string" , "cardinality" : 1 },
1319+ },
1320+ "limit" : 1000 ,
1321+ })
1322+ time .Sleep (5 * time .Millisecond )
1323+
1324+ w := httptest .NewRecorder ()
1325+ r := httptest .NewRequest ("GET" , "/loki/api/v1/detected_fields?query=%7Bservice_name%3D%22cached-svc%22%7D" , nil )
1326+ p .handleDetectedFields (w , r )
1327+
1328+ if w .Code != http .StatusOK {
1329+ t .Fatalf ("expected stale cached detected_fields response, got %d body=%s" , w .Code , w .Body .String ())
1330+ }
1331+ var resp map [string ]interface {}
1332+ mustUnmarshal (t , w .Body .Bytes (), & resp )
1333+ fields := resp ["fields" ].([]interface {})
1334+ if len (fields ) != 1 || fields [0 ].(map [string ]interface {})["label" ] != "cached_field" {
1335+ t .Fatalf ("expected stale cached detected_fields payload, got %v" , resp )
1336+ }
1337+ }
1338+
1339+ func TestDrilldown_DetectedFields_ReturnsErrorWithoutCacheOnBackendFailure (t * testing.T ) {
1340+ vlBackend := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1341+ http .Error (w , "backend unavailable" , http .StatusBadGateway )
1342+ }))
1343+ defer vlBackend .Close ()
1344+
1345+ p := newGapTestProxy (t , vlBackend .URL )
1346+ w := httptest .NewRecorder ()
1347+ r := httptest .NewRequest ("GET" , "/loki/api/v1/detected_fields?query=%7Bservice_name%3D%22svc%22%7D" , nil )
1348+ p .handleDetectedFields (w , r )
1349+
1350+ if w .Code != http .StatusBadGateway {
1351+ t .Fatalf ("expected 502 when detected_fields has no cache fallback, got %d body=%s" , w .Code , w .Body .String ())
1352+ }
1353+ }
1354+
1355+ func TestDrilldown_DetectedLabels_ServesStaleCacheOnBackendError (t * testing.T ) {
1356+ vlBackend := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1357+ http .Error (w , "backend unavailable" , http .StatusBadGateway )
1358+ }))
1359+ defer vlBackend .Close ()
1360+
1361+ p := newGapTestProxy (t , vlBackend .URL )
1362+ cacheKey := "detected_labels::query=%7Bk8s_cluster_name%3D%22ops-sand%22%7D"
1363+ p .setJSONCacheWithTTL (cacheKey , time .Millisecond , map [string ]interface {}{
1364+ "status" : "success" ,
1365+ "data" : []map [string ]interface {}{
1366+ {"label" : "service_name" , "cardinality" : 1 },
1367+ },
1368+ "detectedLabels" : []map [string ]interface {}{
1369+ {"label" : "service_name" , "cardinality" : 1 },
1370+ },
1371+ "limit" : 1000 ,
1372+ })
1373+ time .Sleep (5 * time .Millisecond )
1374+
1375+ w := httptest .NewRecorder ()
1376+ r := httptest .NewRequest ("GET" , "/loki/api/v1/detected_labels?query=%7Bk8s_cluster_name%3D%22ops-sand%22%7D" , nil )
1377+ p .handleDetectedLabels (w , r )
1378+
1379+ if w .Code != http .StatusOK {
1380+ t .Fatalf ("expected stale cached detected_labels response, got %d body=%s" , w .Code , w .Body .String ())
1381+ }
1382+ var resp map [string ]interface {}
1383+ mustUnmarshal (t , w .Body .Bytes (), & resp )
1384+ items := resp ["detectedLabels" ].([]interface {})
1385+ if len (items ) != 1 || items [0 ].(map [string ]interface {})["label" ] != "service_name" {
1386+ t .Fatalf ("expected stale cached detected_labels payload, got %v" , resp )
1387+ }
1388+ }
1389+
1390+ func TestDrilldown_DetectedFieldValues_ServesStaleCacheOnBackendError (t * testing.T ) {
1391+ vlBackend := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1392+ http .Error (w , "backend unavailable" , http .StatusBadGateway )
1393+ }))
1394+ defer vlBackend .Close ()
1395+
1396+ p := newGapTestProxy (t , vlBackend .URL )
1397+ cacheKey := "detected_field_values::service_name:query=%7Bservice_name%3D%22cached-svc%22%7D"
1398+ p .setJSONCacheWithTTL (cacheKey , time .Millisecond , map [string ]interface {}{
1399+ "status" : "success" ,
1400+ "data" : []string {"cached-svc" },
1401+ "values" : []string {"cached-svc" },
1402+ "limit" : 1000 ,
1403+ })
1404+ time .Sleep (5 * time .Millisecond )
1405+
1406+ w := httptest .NewRecorder ()
1407+ r := httptest .NewRequest ("GET" , "/loki/api/v1/detected_field/service_name/values?query=%7Bservice_name%3D%22cached-svc%22%7D" , nil )
1408+ p .handleDetectedFieldValues (w , r )
1409+
1410+ if w .Code != http .StatusOK {
1411+ t .Fatalf ("expected stale cached detected_field_values response, got %d body=%s" , w .Code , w .Body .String ())
1412+ }
1413+ var resp map [string ]interface {}
1414+ mustUnmarshal (t , w .Body .Bytes (), & resp )
1415+ values := resp ["values" ].([]interface {})
1416+ if len (values ) != 1 || values [0 ].(string ) != "cached-svc" {
1417+ t .Fatalf ("expected stale cached detected_field_values payload, got %v" , resp )
1418+ }
1419+ }
1420+
13041421func TestDetectedLabelValuesForField_ResolvesKnownUnderscoreAlias (t * testing.T ) {
13051422 backend := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
13061423 switch r .URL .Path {
0 commit comments