mirror of https://github.com/linkerd/linkerd2.git
Fix pointer copying (#330)
The Public APIs stat endpoint copies a slice of values to a slice of pointers prior to gRPC response. Go's range clause re-uses the same pointer for each iteration of the loop, causing a slice of {1,2,3} becoming {3,3,3}. Fix the range loop to directly reference pointers in the slice of values, ignoring the range variable. Also add tests to catch this case. Signed-off-by: Andrew Seigner <siggy@buoyant.io>
This commit is contained in:
parent
8bc497a057
commit
261586b862
|
@ -107,8 +107,8 @@ func (s *grpcServer) Stat(ctx context.Context, req *pb.MetricRequest) (*pb.Metri
|
||||||
log.Errorf("Stat -> queryMetric failed with: %s", err)
|
log.Errorf("Stat -> queryMetric failed with: %s", err)
|
||||||
err = result.err
|
err = result.err
|
||||||
} else {
|
} else {
|
||||||
for _, ser := range result.series {
|
for i := range result.series {
|
||||||
metrics = append(metrics, &ser)
|
metrics = append(metrics, &result.series[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,23 @@ func TestStat(t *testing.T) {
|
||||||
&telemetry.Sample{
|
&telemetry.Sample{
|
||||||
Values: []*telemetry.SampleValue{
|
Values: []*telemetry.SampleValue{
|
||||||
&telemetry.SampleValue{Value: 1, TimestampMs: 2},
|
&telemetry.SampleValue{Value: 1, TimestampMs: 2},
|
||||||
|
&telemetry.SampleValue{Value: 3, TimestampMs: 4},
|
||||||
},
|
},
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
sourceDeployLabel: "sourceDeployLabel",
|
sourceDeployLabel: "sourceDeployLabel",
|
||||||
targetDeployLabel: "targetDeployLabel",
|
targetDeployLabel: "targetDeployLabel",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
&telemetry.Sample{
|
||||||
|
Values: []*telemetry.SampleValue{
|
||||||
|
&telemetry.SampleValue{Value: 5, TimestampMs: 6},
|
||||||
|
&telemetry.SampleValue{Value: 7, TimestampMs: 8},
|
||||||
|
},
|
||||||
|
Labels: map[string]string{
|
||||||
|
sourceDeployLabel: "sourceDeployLabel2",
|
||||||
|
targetDeployLabel: "targetDeployLabel2",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mReq: &pb.MetricRequest{
|
mReq: &pb.MetricRequest{
|
||||||
|
@ -67,6 +78,27 @@ func TestStat(t *testing.T) {
|
||||||
Value: &pb.MetricValue{Value: &pb.MetricValue_Gauge{Gauge: 1}},
|
Value: &pb.MetricValue{Value: &pb.MetricValue_Gauge{Gauge: 1}},
|
||||||
TimestampMs: 2,
|
TimestampMs: 2,
|
||||||
},
|
},
|
||||||
|
&pb.MetricDatapoint{
|
||||||
|
Value: &pb.MetricValue{Value: &pb.MetricValue_Gauge{Gauge: 3}},
|
||||||
|
TimestampMs: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&pb.MetricSeries{
|
||||||
|
Name: pb.MetricName_REQUEST_RATE,
|
||||||
|
Metadata: &pb.MetricMetadata{
|
||||||
|
SourceDeploy: "sourceDeployLabel2",
|
||||||
|
TargetDeploy: "targetDeployLabel2",
|
||||||
|
},
|
||||||
|
Datapoints: []*pb.MetricDatapoint{
|
||||||
|
&pb.MetricDatapoint{
|
||||||
|
Value: &pb.MetricValue{Value: &pb.MetricValue_Gauge{Gauge: 5}},
|
||||||
|
TimestampMs: 6,
|
||||||
|
},
|
||||||
|
&pb.MetricDatapoint{
|
||||||
|
Value: &pb.MetricValue{Value: &pb.MetricValue_Gauge{Gauge: 7}},
|
||||||
|
TimestampMs: 8,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue