Skip to content

Commit

Permalink
Merge pull request #1078 from alphagov/151014551-improved-metrics
Browse files Browse the repository at this point in the history
[#151014551] Tag app and service `paas-metrics` with their org's quota
  • Loading branch information
dcarley committed Oct 30, 2017
2 parents 87ff1bf + ef3c59f commit bfe663d
Showing 1 changed file with 180 additions and 33 deletions.
213 changes: 180 additions & 33 deletions tools/metrics/gauges.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main

import (
"fmt"
"log"
"net/url"
"time"

Expand Down Expand Up @@ -116,32 +118,68 @@ func AppCountGauge(c *Client, interval time.Duration) MetricReadCloser {
if err != nil {
return err
}
started := 0
stopped := 0
spaces, err := c.cf.ListSpaces()
if err != nil {
return err
}
orgs, err := c.cf.ListOrgs()
if err != nil {
return err
}
orgQuotas, err := c.cf.ListOrgQuotas()
if err != nil {
return err
}

// Number of relevant apps in
// - APP_STATE: string of whether each app is "started" or "stopped"
// - ORG_IS_TRIAL: boolean of whether each app is owned by a trial organisation
// counters[APP_STATE][ORG_IS_TRIAL]
counters := map[string]map[bool]int{
"started": map[bool]int{},
"stopped": map[bool]int{},
}
for _, app := range apps {
space := findSpace(spaces, app.SpaceGuid)
if space == nil {
log.Printf("Space was not found for app %s\n", app.Guid)
continue
}
org := findOrg(orgs, space.OrganizationGuid)
if org == nil {
log.Printf("Org was not found for app %s in space %s\n", app.Guid, space.Guid)
continue
}
orgQuota := findOrgQuota(orgQuotas, org.QuotaDefinitionGuid)
if orgQuota == nil {
log.Printf("Org Quota was not found for app %s in org %s\n", app.Guid, org.Guid)
continue
}
orgIsTrial := isOrgQuotaTrial(orgQuota)
if app.State == "STARTED" {
started += 1
counters["started"][orgIsTrial]++
}
if app.State == "STOPPED" {
stopped += 1
counters["stopped"][orgIsTrial]++
}
}
return w.WriteMetrics([]Metric{
{
Kind: Gauge,
Time: time.Now(),
Name: "apps.count",
Value: float64(started),
Tags: []string{"state:running"},
},
{
Kind: Gauge,
Time: time.Now(),
Name: "apps.count",
Value: float64(stopped),
Tags: []string{"state:stopped"},
},
})

metrics := []Metric{}
for state, countByTrial := range counters {
for orgIsTrial, count := range countByTrial {
metrics = append(metrics, Metric{
Kind: Gauge,
Time: time.Now(),
Name: "apps.count",
Value: float64(count),
Tags: []string{
"state:" + state,
fmt.Sprintf("trial_org:%t", orgIsTrial),
},
})
}
}
return w.WriteMetrics(metrics)
})
}

Expand All @@ -155,27 +193,90 @@ func ServiceCountGauge(c *Client, interval time.Duration) MetricReadCloser {
if err != nil {
return nil
}
counters := map[string]int{}
servicePlans, err := c.cf.ListServicePlans()
if err != nil {
return nil
}
spaces, err := c.cf.ListSpaces()
if err != nil {
return err
}
orgs, err := c.cf.ListOrgs()
if err != nil {
return err
}
orgQuotas, err := c.cf.ListOrgQuotas()
if err != nil {
return err
}

// Number of relevant service instances in
// - ORG_IS_TRIAL: boolean of whether each instance is owned by a trial organisation
// - SERVICE_PLAN_IS_FREE: whether the instance's service plan is free
// - NAME_OF_SERVICE: e.g., "mysql" or "postgres"
// counters[ORG_IS_TRIAL][SERVICE_PLAN_IS_FREE][NAME_OF_SERVICE]
counters := map[bool]map[bool]map[string]int{
true: map[bool]map[string]int{
true: map[string]int{},
false: map[string]int{},
},
false: map[bool]map[string]int{
true: map[string]int{},
false: map[string]int{},
},
}
for _, instance := range serviceInstances {
service := findService(services, instance.ServiceGuid)
if service == nil {
log.Printf("Service was not found for service instance %s\n", instance.Guid)
continue
}
if service.Label == "" {
log.Printf("Service label was empty for service %s and service instance %s\n", service.Guid, instance.Guid)
continue
}
servicePlan := findServicePlan(servicePlans, instance.ServicePlanGuid)
if servicePlan == nil {
log.Printf("Error finding service plan for service instance %s: %s\n", instance.Guid, err)
continue
}
space := findSpace(spaces, instance.SpaceGuid)
if space == nil {
log.Printf("Space was not found for service instance %s\n", instance.Guid)
continue
}
org := findOrg(orgs, space.OrganizationGuid)
if org == nil {
log.Printf("Org was not found for service instance %s in space %s\n", instance.Guid, space.Guid)
continue
}
orgQuota := findOrgQuota(orgQuotas, org.QuotaDefinitionGuid)
if err != nil {
log.Printf("Org Quota was not found for service instance %s in org %s\n", instance.Guid, org.Guid)
continue
}
counters[service.Label]++
orgIsTrial := isOrgQuotaTrial(orgQuota)
servicePlanIsFree := isServicePlanFree(servicePlan)
counters[orgIsTrial][servicePlanIsFree][service.Label]++
}
metrics := []Metric{}
for serviceName, count := range counters {
metrics = append(metrics, Metric{
Kind: Gauge,
Time: time.Now(),
Name: "services.provisioned",
Value: float64(count),
Tags: []string{"type:" + serviceName},
})

metrics := []Metric{}
for orgIsTrial, x := range counters {
for servicePlanIsFree, y := range x {
for serviceLabel, count := range y {
metrics = append(metrics, Metric{
Kind: Gauge,
Time: time.Now(),
Name: "services.provisioned",
Value: float64(count),
Tags: []string{
"type:" + serviceLabel,
fmt.Sprintf("trial_org:%t", orgIsTrial),
fmt.Sprintf("free_service:%t", servicePlanIsFree),
},
})
}
}
}
return w.WriteMetrics(metrics)
})
Expand All @@ -191,10 +292,10 @@ func OrgCountGauge(c *Client, interval time.Duration) MetricReadCloser {
for _, org := range orgs {
quota, err := org.Quota()
if err != nil {
return err
log.Printf("Error finding org quota for org %s: %s\n", org.Guid, err)
continue
}
counters[quota.Name]++

}
metrics := []Metric{}
for name, count := range counters {
Expand Down Expand Up @@ -274,3 +375,49 @@ func findService(services []cfclient.Service, guid string) *cfclient.Service {
}
return nil
}

func findServicePlan(servicePlans []cfclient.ServicePlan, guid string) *cfclient.ServicePlan {
for _, servicePlan := range servicePlans {
if servicePlan.Guid == guid {
return &servicePlan
}
}
return nil
}

func findSpace(spaces []cfclient.Space, guid string) *cfclient.Space {
for _, space := range spaces {
if space.Guid == guid {
return &space
}
}
return nil
}

func findOrg(orgs []cfclient.Org, guid string) *cfclient.Org {
for _, org := range orgs {
if org.Guid == guid {
return &org
}
}
return nil
}

func findOrgQuota(orgQuotas []cfclient.OrgQuota, guid string) *cfclient.OrgQuota {
for _, orgQuota := range orgQuotas {
if orgQuota.Guid == guid {
return &orgQuota
}
}
return nil
}

// Determine if an organisation is on a trial plan.
func isOrgQuotaTrial(quota *cfclient.OrgQuota) bool {
return quota.Name == "default"
}

// Determine if a service plan is free.
func isServicePlanFree(plan *cfclient.ServicePlan) bool {
return plan.Name == "Free"
}

0 comments on commit bfe663d

Please sign in to comment.