-
Notifications
You must be signed in to change notification settings - Fork 7
/
service.go
136 lines (120 loc) · 3.89 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package callhome
import (
"bytes"
"context"
"encoding/json"
"strings"
"text/template"
"time"
)
const pageLimit = 1000
// Service to receive homing telemetry data, persist and retrieve it.
type Service interface {
// Save saves the homing telemetry data and its location information.
Save(ctx context.Context, t Telemetry) error
// Retrieve retrieves homing telemetry data from the specified repository.
Retrieve(ctx context.Context, pm PageMetadata, filters TelemetryFilters) (TelemetryPage, error)
// RetrieveSummary gets distinct countries and ip addresses
RetrieveSummary(ctx context.Context, filters TelemetryFilters) (TelemetrySummary, error)
// ServeUI gets the callhome index html page
ServeUI(ctx context.Context, filters TelemetryFilters) ([]byte, error)
}
var _ Service = (*telemetryService)(nil)
type telemetryService struct {
repo TelemetryRepo
locSvc LocationService
}
// New creates a new instance of the telemetry service.
func New(repo TelemetryRepo, locSvc LocationService) Service {
return &telemetryService{
repo: repo,
locSvc: locSvc,
}
}
// Retrieve retrieves homing telemetry data from the specified repository.
func (ts *telemetryService) Retrieve(ctx context.Context, pm PageMetadata, filters TelemetryFilters) (TelemetryPage, error) {
return ts.repo.RetrieveAll(ctx, pm, filters)
}
// Save saves the homing telemetry data and its location information.
func (ts *telemetryService) Save(ctx context.Context, t Telemetry) error {
locRec, err := ts.locSvc.GetLocation(ctx, t.IpAddress)
if err != nil {
return err
}
t.City = locRec.City
t.Country = locRec.Country_long
t.Latitude = float64(locRec.Latitude)
t.Longitude = float64(locRec.Longitude)
t.LastSeen = time.Now()
return ts.repo.Save(ctx, t)
}
func (ts *telemetryService) RetrieveSummary(ctx context.Context, filters TelemetryFilters) (TelemetrySummary, error) {
return ts.repo.RetrieveSummary(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"))
if filters.From.IsZero() && filters.To.IsZero() && filters.City == "" && filters.Country == "" && filters.Service == "" && filters.Version == "" {
filters.From = time.Now().Add(-time.Hour)
}
summary, err := ts.repo.RetrieveSummary(ctx, filters)
if err != nil {
return nil, err
}
unfilteredSummary, err := ts.repo.RetrieveSummary(ctx, TelemetryFilters{})
if err != nil {
return nil, err
}
telPage, err := ts.repo.RetrieveAll(ctx, PageMetadata{Limit: pageLimit}, filters)
if err != nil {
return nil, err
}
pg, err := json.Marshal(telPage)
if err != nil {
return nil, err
}
countries, err := json.Marshal(summary.Countries)
if err != nil {
return nil, err
}
var from, to string
if !filters.From.IsZero() {
from = filters.From.Format(time.RFC3339)
from = strings.ReplaceAll(from, "Z", "")
}
if !filters.To.IsZero() {
to = filters.To.Format(time.RFC3339)
to = strings.ReplaceAll(to, "Z", "")
}
data := struct {
Countries string
Cities string
FilterCountries []CountrySummary
FilterCities []string
FilterServices []string
FilterVersions []string
NoDeployments int
NoCountries int
MapData string
From string
To string
}{
Countries: string(countries),
FilterCountries: unfilteredSummary.Countries,
FilterCities: unfilteredSummary.Cities,
FilterServices: unfilteredSummary.Services,
FilterVersions: unfilteredSummary.Versions,
NoDeployments: summary.TotalDeployments,
NoCountries: len(summary.Countries),
MapData: string(pg),
From: from,
To: to,
}
var res bytes.Buffer
if err = tmpl.Execute(&res, data); err != nil {
return nil, err
}
return res.Bytes(), nil
}