diff --git a/api/endpoint.go b/api/endpoint.go index 1fe0690..6c5899d 100644 --- a/api/endpoint.go +++ b/api/endpoint.go @@ -83,6 +83,7 @@ func retrieveSummaryEndpoint(svc callhome.Service) endpoint.Endpoint { } return telemetrySummaryRes{ Countries: summary.Countries, + Cities: summary.Cities, TotalDeployments: summary.TotalDeployments, }, nil } diff --git a/api/responses.go b/api/responses.go index c03516d..e58b2be 100644 --- a/api/responses.go +++ b/api/responses.go @@ -89,6 +89,7 @@ func (res uiRes) Headers() map[string]string { type telemetrySummaryRes struct { Countries []callhome.CountrySummary `json:"countries,omitempty"` + Cities []callhome.CitySummary `json:"cities,omitempty"` TotalDeployments int `json:"total_deployments,omitempty"` } diff --git a/service.go b/service.go index 8cef761..b83701c 100644 --- a/service.go +++ b/service.go @@ -59,22 +59,22 @@ func (ts *telemetryService) Save(ctx context.Context, t Telemetry) error { } func (ts *telemetryService) RetrieveSummary(ctx context.Context, filters TelemetryFilters) (TelemetrySummary, error) { - return ts.repo.RetrieveDistinctIPsCountries(ctx, filters) + return ts.repo.RetrieveDistinctIPs(ctx, filters) } // ServeUI gets the callhome index html page func (ts *telemetryService) ServeUI(ctx context.Context, filters TelemetryFilters) ([]byte, error) { tmpl := template.Must(template.ParseFiles("./web/template/index.html")) - summary, err := ts.repo.RetrieveDistinctIPsCountries(ctx, filters) + summary, err := ts.repo.RetrieveDistinctIPs(ctx, filters) if err != nil { return nil, err } - allCountries, err := ts.repo.RetrieveDistinctIPsCountries(ctx, TelemetryFilters{}) + allCountries, err := ts.repo.RetrieveDistinctIPs(ctx, TelemetryFilters{}) if err != nil { return nil, err } - allCities, err := ts.repo.RetrieveDistinctIPsCountries(ctx, filters) + allCities, err := ts.repo.RetrieveDistinctIPs(ctx, filters) if err != nil { return nil, err } @@ -92,6 +92,11 @@ func (ts *telemetryService) ServeUI(ctx context.Context, filters TelemetryFilter return nil, err } + cities, err := json.Marshal(summary.Cities) + if err != nil { + return nil, err + } + filterCountries := allCountries.Countries filterCities := allCities.Cities @@ -104,6 +109,7 @@ func (ts *telemetryService) ServeUI(ctx context.Context, filters TelemetryFilter } data := struct { Countries string + Cities string FilterCountries []CountrySummary FilterCities []CitySummary NoDeployments int @@ -113,6 +119,7 @@ func (ts *telemetryService) ServeUI(ctx context.Context, filters TelemetryFilter To string }{ Countries: string(countries), + Cities: string(cities), FilterCountries: filterCountries, FilterCities: filterCities, NoDeployments: summary.TotalDeployments, diff --git a/telemetry.go b/telemetry.go index abc8244..dbc7fe3 100644 --- a/telemetry.go +++ b/telemetry.go @@ -51,10 +51,9 @@ type CitySummary struct { } type TelemetrySummary struct { - Countries []CountrySummary `json:"countries,omitempty"` - TotalDeployments int `json:"total_deployments,omitempty"` - Cities []CitySummary `json:"cities,omitempty"` - TotalCityDeployments int `json:"total_city_deployments,omitempty"` + Countries []CountrySummary `json:"countries,omitempty"` + Cities []CitySummary `json:"cities,omitempty"` + TotalDeployments int `json:"total_deployments,omitempty"` } // TelemetryRepository specifies an account persistence API. @@ -65,6 +64,6 @@ type TelemetryRepo interface { // RetrieveAll retrieves all telemetry events. RetrieveAll(ctx context.Context, pm PageMetadata, filters TelemetryFilters) (TelemetryPage, error) - // RetrieveDistinctIPsCOuntries gets distinct ip addresses and countries from database. - RetrieveDistinctIPsCountries(ctx context.Context, filters TelemetryFilters) (TelemetrySummary, error) + // RetrieveDistinctIPs gets distinct ip addresses and countries from database. + RetrieveDistinctIPs(ctx context.Context, filters TelemetryFilters) (TelemetrySummary, error) } diff --git a/timescale/mocks/mocks.go b/timescale/mocks/mocks.go index 74796f5..d1b8092 100644 --- a/timescale/mocks/mocks.go +++ b/timescale/mocks/mocks.go @@ -30,8 +30,8 @@ func (mr *mockRepo) Save(ctx context.Context, t callhome.Telemetry) error { return r0 } -// RetrieveDistinctIPsCountries retrieve distinct -func (*mockRepo) RetrieveDistinctIPsCountries(ctx context.Context, filter callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { +// RetrieveDistinctIPs retrieve distinct +func (*mockRepo) RetrieveDistinctIPs(ctx context.Context, filter callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { return callhome.TelemetrySummary{}, nil } diff --git a/timescale/timescale.go b/timescale/timescale.go index b992c2a..503bf9f 100644 --- a/timescale/timescale.go +++ b/timescale/timescale.go @@ -126,16 +126,16 @@ func (r repo) Save(ctx context.Context, t callhome.Telemetry) error { } -// RetrieveDistinctIPsCountries retrieve distinct -func (r repo) RetrieveDistinctIPsCountries(ctx context.Context, filters callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { +// RetrieveDistinctIPs retrieve distinct +func (r repo) RetrieveDistinctIPs(ctx context.Context, filters callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { filterQuery, params := generateQuery(filters) + var summary callhome.TelemetrySummary q := fmt.Sprintf(`select count(distinct ip_address), country from telemetry %s group by country;`, filterQuery) rows, err := r.db.NamedQuery(q, params) if err != nil { return callhome.TelemetrySummary{}, err } defer rows.Close() - var summary callhome.TelemetrySummary for rows.Next() { var val callhome.CountrySummary if err := rows.StructScan(&val); err != nil { @@ -146,6 +146,20 @@ func (r repo) RetrieveDistinctIPsCountries(ctx context.Context, filters callhome for _, country := range summary.Countries { summary.TotalDeployments += country.NoDeployments } + + q1 := `select city from telemetry;` + cityRows, err := r.db.NamedQuery(q1, params) + if err != nil { + return callhome.TelemetrySummary{}, err + } + defer cityRows.Close() + for cityRows.Next() { + var val callhome.CitySummary + if err := cityRows.StructScan(&val); err != nil { + return callhome.TelemetrySummary{}, err + } + summary.Cities = append(summary.Cities, val) + } return summary, nil } diff --git a/timescale/tracing/tracing.go b/timescale/tracing/tracing.go index ab1a213..58a6c3b 100644 --- a/timescale/tracing/tracing.go +++ b/timescale/tracing/tracing.go @@ -35,11 +35,11 @@ func (rt *repoTracer) RetrieveAll(ctx context.Context, pm callhome.PageMetadata, return rt.repo.RetrieveAll(ctx, pm, filter) } -// RetrieveDistinctIPsCountries adds tracing middleware to retrieve distinct ips countries method. -func (rt *repoTracer) RetrieveDistinctIPsCountries(ctx context.Context, filter callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { +// RetrieveDistinctIPs adds tracing middleware to retrieve distinct ips countries method. +func (rt *repoTracer) RetrieveDistinctIPs(ctx context.Context, filter callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { ctx, span := rt.tracer.Start(ctx, retrieveDistinctIPsCountriesOp) defer span.End() - return rt.repo.RetrieveDistinctIPsCountries(ctx, filter) + return rt.repo.RetrieveDistinctIPs(ctx, filter) } // Save adds tracing middleware to save method. diff --git a/web/static/style.css b/web/static/style.css index 9bf7878..8ad002d 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -20,7 +20,7 @@ body { flex-grow: 1; height: 95%; width: 100%; - + } .btn { diff --git a/web/template/index.html b/web/template/index.html index 5badcf8..c458e3f 100644 --- a/web/template/index.html +++ b/web/template/index.html @@ -103,6 +103,8 @@

Apply Filters

var toDate = toDateInput ? new Date(toDateInput).toISOString() : ''; var url = `/?from=${encodeURIComponent(fromDate)}&to=${encodeURIComponent(toDate)}&country=${encodeURIComponent(selectedCountry)}&city=${encodeURIComponent(selectedCity)}`; + + window.location.href = url; }