Skip to content

Commit

Permalink
🕵️
Browse files Browse the repository at this point in the history
  • Loading branch information
geigerj0 committed Apr 24, 2024
1 parent bba20af commit cbaa469
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 34 deletions.
6 changes: 3 additions & 3 deletions src/acceptance/app/dynamic_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,13 @@ var _ = Describe("AutoScaler dynamic policy", func() {
Context("when throughput is less than scaling in threshold", func() {

BeforeEach(func() {
policy = GenerateDynamicScaleInPolicy(1, 2, "throughput", 100)
policy = GenerateDynamicScaleInPolicy(1, 2, "throughput", 30)
initialInstanceCount = 2
})

JustBeforeEach(func() {
ticker = time.NewTicker(10 * time.Second)
// simulate ongoing ~1 requests per second
ticker = time.NewTicker(1 * time.Second)
go func(chan bool) {
defer GinkgoRecover()
for {
Expand All @@ -241,7 +242,6 @@ var _ = Describe("AutoScaler dynamic policy", func() {
WaitForNInstancesRunning(appGUID, 1, 5*time.Minute)
})
})

})

// To check existing aggregated cpu metrics do: cf asm APP_NAME cpu
Expand Down
2 changes: 1 addition & 1 deletion src/autoscaler/eventgenerator/client/log_cache_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (c *LogCacheClient) GetMetrics(appId string, metricType string, startTime t

// return empty metrics if there are no samples, this usually happens in case there were no recent http-requests towards the application
if len(vector.GetSamples()) <= 0 {
return c.emptyAppInstanceMetrics(appId, models.MetricNameThroughput, models.UnitRPS, now)
return c.emptyAppInstanceMetrics(appId, metricType, metricTypeUnit, now)
}

// convert result into autoscaler metric model
Expand Down
238 changes: 208 additions & 30 deletions src/autoscaler/eventgenerator/client/log_cache_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,49 +233,227 @@ var _ = Describe("LogCacheClient", func() {
})
})

When("errors occur reading via PromQL API", func() {
When("PromQL call fails", func() {
It("returns an error", func() {
fakeGoLogCacheReader.PromQLReturns(nil, errors.New("fail"))
_, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)
Expect(err).To(HaveOccurred())
})
})

When("PromQL result is not a vector", func() {
It("returns an error", func() {
fakeGoLogCacheReader.PromQLReturns(nil, nil)
_, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)
Expect(err).To(HaveOccurred())
})
})

When("sample does not contain instance_id", func() {
It("returns an error", func() {
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{
Samples: []*logcache_v1.PromQL_Sample{
{
Metric: map[string]string{
// "instance_id": "0", is missing here
},
},
},
},
},
}, nil)
_, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)
Expect(err).To(HaveOccurred())
})
})

When("instance_id can not be parsed to uint", func() {
It("returns an error", func() {
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{
Samples: []*logcache_v1.PromQL_Sample{
{
Metric: map[string]string{
"instance_id": "iam-no-uint",
},
},
},
},
},
}, nil)
_, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)
Expect(err).To(HaveOccurred())
})
})

When("sample does not contain a point", func() {
It("returns an error", func() {
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{
Samples: []*logcache_v1.PromQL_Sample{
{
Metric: map[string]string{
"instance_id": "0",
},
},
},
},
},
}, nil)
_, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)
Expect(err).To(HaveOccurred())
})
})
})

When("reading throughput metrics", func() {
It("should work", func() {
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{
Samples: []*logcache_v1.PromQL_Sample{
{
Metric: map[string]string{
"instance_id": "0",
When("PromQL API returns a vector with no samples", func() {
It("returns empty metrics", func() {
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{},
},
}, nil)

metrics, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)

Expect(err).To(Not(HaveOccurred()))
Expect(metrics).To(HaveLen(1))

Expect(metrics[0].AppId).To(Equal("app-id"))
Expect(metrics[0].InstanceIndex).To(Equal(uint32(0)))
Expect(metrics[0].Name).To(Equal("throughput"))
Expect(metrics[0].Unit).To(Equal("rps"))
Expect(metrics[0].Value).To(Equal("0"))
})
})

When("promql api returns a vector with samples", func() {
It("returns metrics ", func() {
fakeEnvelopeProcessor.GetCollectionIntervalReturns(40 * time.Second)
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{
Samples: []*logcache_v1.PromQL_Sample{
{
Metric: map[string]string{
"instance_id": "0",
},
Point: &logcache_v1.PromQL_Point{
Value: 123,
},
},
Point: &logcache_v1.PromQL_Point{
Value: 123,
{
Metric: map[string]string{
"instance_id": "1",
},
Point: &logcache_v1.PromQL_Point{
Value: 321,
},
},
},
{
Metric: map[string]string{
"instance_id": "1",
},
},
}, nil)

metrics, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)

_, query, _ := fakeGoLogCacheReader.PromQLArgsForCall(0)
Expect(query).To(Equal("sum by (instance_id) (count_over_time(http{source_id='app-id'}[40s])) / 40"))

Expect(err).To(Not(HaveOccurred()))
Expect(metrics).To(HaveLen(2))

Expect(metrics[0].AppId).To(Equal("app-id"))
Expect(metrics[0].InstanceIndex).To(Equal(uint32(0)))
Expect(metrics[0].Name).To(Equal("throughput"))
Expect(metrics[0].Unit).To(Equal("rps"))
Expect(metrics[0].Value).To(Equal("123"))

Expect(metrics[1].AppId).To(Equal("app-id"))
Expect(metrics[1].InstanceIndex).To(Equal(uint32(1)))
Expect(metrics[1].Name).To(Equal("throughput"))
Expect(metrics[1].Unit).To(Equal("rps"))
Expect(metrics[1].Value).To(Equal("321"))
})
})
})

When("reading responsetime metrics", func() {
When("PromQL API returns a vector with no samples", func() {
It("returns empty metrics", func() {
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{},
},
}, nil)

metrics, err := logCacheClient.GetMetrics("app-id", "responsetime", startTime, endTime)

Expect(err).To(Not(HaveOccurred()))
Expect(metrics).To(HaveLen(1))

Expect(metrics[0].AppId).To(Equal("app-id"))
Expect(metrics[0].InstanceIndex).To(Equal(uint32(0)))
Expect(metrics[0].Name).To(Equal("responsetime"))
Expect(metrics[0].Unit).To(Equal("ms"))
Expect(metrics[0].Value).To(Equal("0"))
})
})

When("promql api returns a vector with samples", func() {
It("reads from PromQL API ", func() {
fakeEnvelopeProcessor.GetCollectionIntervalReturns(40 * time.Second)
fakeGoLogCacheReader.PromQLReturns(&logcache_v1.PromQL_InstantQueryResult{
Result: &logcache_v1.PromQL_InstantQueryResult_Vector{
Vector: &logcache_v1.PromQL_Vector{
Samples: []*logcache_v1.PromQL_Sample{
{
Metric: map[string]string{
"instance_id": "0",
},
Point: &logcache_v1.PromQL_Point{
Value: 200,
},
},
Point: &logcache_v1.PromQL_Point{
Value: 321,
{
Metric: map[string]string{
"instance_id": "1",
},
Point: &logcache_v1.PromQL_Point{
Value: 300,
},
},
},
},
},
},
}, nil)
}, nil)

metrics, err := logCacheClient.GetMetrics("app-id", "responsetime", startTime, endTime)

metrics, err := logCacheClient.GetMetrics("app-id", "throughput", startTime, endTime)
_, query, _ := fakeGoLogCacheReader.PromQLArgsForCall(0)
Expect(query).To(Equal("avg by (instance_id) (max_over_time(http{source_id='app-id'}[40s])) / (1000 * 1000)"))

Expect(err).To(Not(HaveOccurred()))
Expect(metrics).To(HaveLen(2))
Expect(err).To(Not(HaveOccurred()))
Expect(metrics).To(HaveLen(2))

Expect(metrics[0].AppId).To(Equal("app-id"))
Expect(metrics[0].InstanceIndex).To(Equal(uint32(0)))
Expect(metrics[0].Name).To(Equal("throughput"))
Expect(metrics[0].Unit).To(Equal("rps"))
Expect(metrics[0].Value).To(Equal("123"))
Expect(metrics[0].AppId).To(Equal("app-id"))
Expect(metrics[0].InstanceIndex).To(Equal(uint32(0)))
Expect(metrics[0].Name).To(Equal("responsetime"))
Expect(metrics[0].Unit).To(Equal("ms"))
Expect(metrics[0].Value).To(Equal("200"))

Expect(metrics[1].AppId).To(Equal("app-id"))
Expect(metrics[1].InstanceIndex).To(Equal(uint32(1)))
Expect(metrics[1].Name).To(Equal("throughput"))
Expect(metrics[1].Unit).To(Equal("rps"))
Expect(metrics[1].Value).To(Equal("321"))
Expect(metrics[1].AppId).To(Equal("app-id"))
Expect(metrics[1].InstanceIndex).To(Equal(uint32(1)))
Expect(metrics[1].Name).To(Equal("responsetime"))
Expect(metrics[1].Unit).To(Equal("ms"))
Expect(metrics[1].Value).To(Equal("300"))
})
})
})

Expand Down

0 comments on commit cbaa469

Please sign in to comment.