mirror of https://github.com/grafana/grafana.git
				
				
				
			Cloudwatch Logs: Make mixed type fields fallback to being strings (#63981)
* Cloudwatch Logs: make mixed type fields fallback to being strings * addressing pr comments
This commit is contained in:
		
							parent
							
								
									1a5ab1b308
								
							
						
					
					
						commit
						70f600db10
					
				|  | @ -73,9 +73,14 @@ func logsResultsToDataframes(response *cloudwatchlogs.GetQueryResultsOutput) (*d | ||||||
| 				timeField[i] = &parsedTime | 				timeField[i] = &parsedTime | ||||||
| 			} else if numericField, ok := fieldValues[*resultField.Field].([]*float64); ok { | 			} else if numericField, ok := fieldValues[*resultField.Field].([]*float64); ok { | ||||||
| 				parsedFloat, err := strconv.ParseFloat(*resultField.Value, 64) | 				parsedFloat, err := strconv.ParseFloat(*resultField.Value, 64) | ||||||
|  | 
 | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					return nil, err | 					// This can happen if a field has a mix of numeric and non-numeric values.
 | ||||||
|  | 					// In that case, we change the field from a numeric field to a string field.
 | ||||||
|  | 					fieldValues[*resultField.Field] = changeToStringField(rowCount, nonEmptyRows[:i+1], *resultField.Field) | ||||||
|  | 					continue | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				numericField[i] = &parsedFloat | 				numericField[i] = &parsedFloat | ||||||
| 			} else { | 			} else { | ||||||
| 				fieldValues[*resultField.Field].([]*string)[i] = resultField.Value | 				fieldValues[*resultField.Field].([]*string)[i] = resultField.Value | ||||||
|  | @ -145,6 +150,19 @@ func logsResultsToDataframes(response *cloudwatchlogs.GetQueryResultsOutput) (*d | ||||||
| 	return frame, nil | 	return frame, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func changeToStringField(lengthOfValues int, rows [][]*cloudwatchlogs.ResultField, logEventField string) []*string { | ||||||
|  | 	fieldValuesAsStrings := make([]*string, lengthOfValues) | ||||||
|  | 	for i, resultFields := range rows { | ||||||
|  | 		for _, field := range resultFields { | ||||||
|  | 			if *field.Field == logEventField { | ||||||
|  | 				fieldValuesAsStrings[i] = field.Value | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return fieldValuesAsStrings | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func groupResults(results *data.Frame, groupingFieldNames []string) ([]*data.Frame, error) { | func groupResults(results *data.Frame, groupingFieldNames []string) ([]*data.Frame, error) { | ||||||
| 	groupingFields := make([]*data.Field, 0) | 	groupingFields := make([]*data.Field, 0) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -221,6 +221,62 @@ func TestLogsResultsToDataframes(t *testing.T) { | ||||||
| 	assert.ElementsMatch(t, expectedDataframe.Fields, dataframes.Fields) | 	assert.ElementsMatch(t, expectedDataframe.Fields, dataframes.Fields) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestLogsResultsToDataframes_MixedTypes_NumericValuesMixedWithStringFallBackToStringValues(t *testing.T) { | ||||||
|  | 	dataframes, err := logsResultsToDataframes(&cloudwatchlogs.GetQueryResultsOutput{ | ||||||
|  | 		Results: [][]*cloudwatchlogs.ResultField{ | ||||||
|  | 			{ | ||||||
|  | 				&cloudwatchlogs.ResultField{ | ||||||
|  | 					Field: aws.String("numberOrString"), | ||||||
|  | 					Value: aws.String("-1.234"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				&cloudwatchlogs.ResultField{ | ||||||
|  | 					Field: aws.String("numberOrString"), | ||||||
|  | 					Value: aws.String("1"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				&cloudwatchlogs.ResultField{ | ||||||
|  | 					Field: aws.String("numberOrString"), | ||||||
|  | 					Value: aws.String("not a number"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				&cloudwatchlogs.ResultField{ | ||||||
|  | 					Field: aws.String("numberOrString"), | ||||||
|  | 					Value: aws.String("2.000"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		Status: aws.String("ok"), | ||||||
|  | 	}) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 	expectedDataframe := &data.Frame{ | ||||||
|  | 		Name: "CloudWatchLogsResponse", | ||||||
|  | 		Fields: []*data.Field{ | ||||||
|  | 			data.NewField("numberOrString", nil, []*string{ | ||||||
|  | 				aws.String("-1.234"), | ||||||
|  | 				aws.String("1"), | ||||||
|  | 				aws.String("not a number"), | ||||||
|  | 				aws.String("2.000"), | ||||||
|  | 			}), | ||||||
|  | 		}, | ||||||
|  | 		RefID: "", | ||||||
|  | 		Meta: &data.FrameMeta{ | ||||||
|  | 			Custom: map[string]interface{}{ | ||||||
|  | 				"Status": "ok", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	assert.Equal(t, expectedDataframe.Name, dataframes.Name) | ||||||
|  | 	assert.Equal(t, expectedDataframe.RefID, dataframes.RefID) | ||||||
|  | 	assert.Equal(t, expectedDataframe.Meta, dataframes.Meta) | ||||||
|  | 	assert.ElementsMatch(t, expectedDataframe.Fields, dataframes.Fields) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestGroupKeyGeneration(t *testing.T) { | func TestGroupKeyGeneration(t *testing.T) { | ||||||
| 	logField := data.NewField("@log", data.Labels{}, []*string{ | 	logField := data.NewField("@log", data.Labels{}, []*string{ | ||||||
| 		aws.String("fakelog-a"), | 		aws.String("fakelog-a"), | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue