Skip to content

Commit 0afcdc3

Browse files
committed
Merge branch '299-engine-telemetry' into 'master'
feat: collect aggregated data to have statistics about DLE usage and trends (#299) Closes #299 See merge request postgres-ai/database-lab!348
2 parents 76c3cb9 + e92478c commit 0afcdc3

34 files changed

+510
-43
lines changed

api/swagger-spec/dblab_server_swagger.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,6 @@ paths:
404404
responses:
405405
200:
406406
description: "Successful operation"
407-
content:
408-
text/json:
409407
400:
410408
description: "Bad request"
411409
schema:
@@ -522,6 +520,8 @@ definitions:
522520
startedAt:
523521
type: "string"
524522
format: "date-time"
523+
telemetry:
524+
type: boolean
525525

526526
PoolEntry:
527527
type: "object"
@@ -593,11 +593,9 @@ definitions:
593593
lastRefresh:
594594
type: "string"
595595
format: "date-time"
596-
nullable: true
597596
nextRefresh:
598597
type: "string"
599598
format: "date-time"
600-
nullable: true
601599

602600
Provisioner:
603601
type: "object"

cmd/cli/commands/clone/actions.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ func list(cliCtx *cli.Context) error {
3939

4040
defer func() { _ = body.Close() }()
4141

42-
var viewCloneList *models.CloneListView
42+
viewCloneList := &models.CloneListView{
43+
Clones: make([]*models.CloneView, 0),
44+
}
4345

4446
if err := json.NewDecoder(body).Decode(&viewCloneList); err != nil {
4547
return err

cmd/cli/commands/config/command_list.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ func CommandList() []*cli.Command {
3131
&cli.StringFlag{
3232
Name: "token",
3333
Usage: "verification token of Database Lab instance",
34-
Required: true,
3534
},
3635
&cli.BoolFlag{
3736
Name: "insecure",

cmd/cli/commands/global/command_list.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ func List() []*cli.Command {
3232
&cli.StringFlag{
3333
Name: "token",
3434
Usage: "verification token of Database Lab instance",
35-
Required: true,
3635
},
3736
&cli.BoolFlag{
3837
Name: "insecure",

cmd/database-lab/main.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import (
3232
"gitlab.com/postgres-ai/database-lab/v2/pkg/services/provision/resources"
3333
"gitlab.com/postgres-ai/database-lab/v2/pkg/services/provision/runners"
3434
"gitlab.com/postgres-ai/database-lab/v2/pkg/srv"
35+
"gitlab.com/postgres-ai/database-lab/v2/pkg/telemetry"
3536
"gitlab.com/postgres-ai/database-lab/v2/pkg/util/networks"
37+
"gitlab.com/postgres-ai/database-lab/v2/version"
3638
)
3739

3840
const (
@@ -47,6 +49,10 @@ func main() {
4749

4850
log.Msg("Database Lab Instance ID:", cfg.Global.InstanceID)
4951

52+
if cfg.Server.VerificationToken == "" {
53+
log.Warn("Verification Token is empty. Database Lab Engine is insecure")
54+
}
55+
5056
runner := runners.NewLocalRunner(cfg.Provision.UseSudo)
5157

5258
pm := pool.NewPoolManager(&cfg.PoolManager, runner)
@@ -96,8 +102,14 @@ func main() {
96102
shutdownDatabaseLabEngine(shutdownCtx, dockerCLI, cfg.Global, pm.First().Pool())
97103
}
98104

105+
tm, err := telemetry.New(cfg.Global)
106+
if err != nil {
107+
log.Errf(errors.WithMessage(err, "failed to initialize a telemetry service").Error())
108+
return
109+
}
110+
99111
// Create a new retrieval service to prepare a data directory and start snapshotting.
100-
retrievalSvc := retrieval.New(cfg, dockerCLI, pm, runner)
112+
retrievalSvc := retrieval.New(cfg, dockerCLI, pm, tm, runner)
101113

102114
if err := retrievalSvc.Run(ctx); err != nil {
103115
log.Err("Failed to run the data retrieval service:", err)
@@ -116,7 +128,7 @@ func main() {
116128

117129
observingChan := make(chan string, 1)
118130

119-
cloningSvc := cloning.NewBase(&cfg.Cloning, provisionSvc, observingChan)
131+
cloningSvc := cloning.NewBase(&cfg.Cloning, provisionSvc, tm, observingChan)
120132
if err = cloningSvc.Run(ctx); err != nil {
121133
log.Err(err)
122134
emergencyShutdown()
@@ -129,10 +141,17 @@ func main() {
129141

130142
go removeObservingClones(observingChan, obs)
131143

132-
server := srv.NewServer(&cfg.Server, &cfg.Global, cloningSvc, retrievalSvc, platformSvc, dockerCLI, obs, est, pm)
144+
tm.SendEvent(ctx, telemetry.EngineStartedEvent, telemetry.EngineStarted{
145+
EngineVersion: version.GetVersion(),
146+
DBVersion: provisionSvc.DetectDBVersion(),
147+
Pools: pm.CollectPoolStat(),
148+
Restore: retrievalSvc.CollectRestoreTelemetry(),
149+
})
150+
151+
server := srv.NewServer(&cfg.Server, &cfg.Global, cloningSvc, retrievalSvc, platformSvc, dockerCLI, obs, est, pm, tm)
133152
shutdownCh := setShutdownListener()
134153

135-
go setReloadListener(ctx, provisionSvc, retrievalSvc, pm, cloningSvc, platformSvc, est, server)
154+
go setReloadListener(ctx, provisionSvc, tm, retrievalSvc, pm, cloningSvc, platformSvc, est, server)
136155

137156
server.InitHandlers()
138157

@@ -155,9 +174,10 @@ func main() {
155174

156175
shutdownDatabaseLabEngine(shutdownCtx, dockerCLI, cfg.Global, pm.First().Pool())
157176
cloningSvc.SaveClonesState()
177+
tm.SendEvent(ctx, telemetry.EngineStoppedEvent, telemetry.EngineStopped{Uptime: server.Uptime()})
158178
}
159179

160-
func reloadConfig(ctx context.Context, provisionSvc *provision.Provisioner, retrievalSvc *retrieval.Retrieval,
180+
func reloadConfig(ctx context.Context, provisionSvc *provision.Provisioner, tm *telemetry.Agent, retrievalSvc *retrieval.Retrieval,
161181
pm *pool.Manager, cloningSvc *cloning.Base, platformSvc *platform.Service, est *estimator.Estimator, server *srv.Server) error {
162182
cfg, err := config.LoadConfiguration()
163183
if err != nil {
@@ -187,6 +207,7 @@ func reloadConfig(ctx context.Context, provisionSvc *provision.Provisioner, retr
187207
}
188208

189209
provisionSvc.Reload(cfg.Provision, dbCfg)
210+
tm.Reload(cfg.Global)
190211
retrievalSvc.Reload(ctx, cfg)
191212
cloningSvc.Reload(cfg.Cloning)
192213
platformSvc.Reload(newPlatformSvc)
@@ -196,15 +217,15 @@ func reloadConfig(ctx context.Context, provisionSvc *provision.Provisioner, retr
196217
return nil
197218
}
198219

199-
func setReloadListener(ctx context.Context, provisionSvc *provision.Provisioner, retrievalSvc *retrieval.Retrieval,
220+
func setReloadListener(ctx context.Context, provisionSvc *provision.Provisioner, tm *telemetry.Agent, retrievalSvc *retrieval.Retrieval,
200221
pm *pool.Manager, cloningSvc *cloning.Base, platformSvc *platform.Service, est *estimator.Estimator, server *srv.Server) {
201222
reloadCh := make(chan os.Signal, 1)
202223
signal.Notify(reloadCh, syscall.SIGHUP)
203224

204225
for range reloadCh {
205226
log.Msg("Reloading configuration")
206227

207-
if err := reloadConfig(ctx, provisionSvc, retrievalSvc, pm, cloningSvc, platformSvc, est, server); err != nil {
228+
if err := reloadConfig(ctx, provisionSvc, tm, retrievalSvc, pm, cloningSvc, platformSvc, est, server); err != nil {
208229
log.Err("Failed to reload configuration", err)
209230
}
210231

cmd/runci/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ func main() {
3838
log.SetDebug(cfg.App.Debug)
3939
log.Dbg("Config loaded: ", cfg)
4040

41+
if cfg.App.VerificationToken == "" {
42+
log.Err("DB Migration Checker is insecure since the Verification Token is empty")
43+
return
44+
}
45+
4146
networkID := discoverNetwork(ctx, cfg, dockerCLI)
4247
if networkID != "" {
4348
hostname := os.Getenv("HOSTNAME")

configs/config.example.logical_generic.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ global:
4242
# Default database name.
4343
dbname: postgres
4444

45+
# Telemetry: anonymous statistics sent to Postgres.ai.
46+
# Used to analyze DLE usage, it helps the DLE maintainers make decisions on product development.
47+
# Please leave it enabled if possible – this will contribute to DLE development.
48+
# The full list of data points being collected: https://postgres.ai/docs/database-lab/telemetry
49+
telemetry:
50+
enabled: true
51+
# Telemetry API URL. To send anonymous telemetry data, keep it default ("https://postgres.ai/api/general").
52+
url: "https://postgres.ai/api/general"
53+
4554
# Manages filesystem pools (in the case of ZFS) or volume groups.
4655
poolManager:
4756
# The full path which contains the pool mount directories. mountDir can contain multiple pool directories.

configs/config.example.logical_rds_iam.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ global:
4242
# Default database name.
4343
dbname: postgres
4444

45+
# Telemetry: anonymous statistics sent to Postgres.ai.
46+
# Used to analyze DLE usage, it helps the DLE maintainers make decisions on product development.
47+
# Please leave it enabled if possible – this will contribute to DLE development.
48+
# The full list of data points being collected: https://postgres.ai/docs/database-lab/telemetry
49+
telemetry:
50+
enabled: true
51+
# Telemetry API URL. To send anonymous telemetry data, keep it default ("https://postgres.ai/api/general").
52+
url: "https://postgres.ai/api/general"
53+
4554
# Manages filesystem pools (in the case of ZFS) or volume groups.
4655
poolManager:
4756
# The full path which contains the pool mount directories. mountDir can contain multiple pool directories.

configs/config.example.physical_generic.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ global:
4242
# Default database name.
4343
dbname: postgres
4444

45+
# Telemetry: anonymous statistics sent to Postgres.ai.
46+
# Used to analyze DLE usage, it helps the DLE maintainers make decisions on product development.
47+
# Please leave it enabled if possible – this will contribute to DLE development.
48+
# The full list of data points being collected: https://postgres.ai/docs/database-lab/telemetry
49+
telemetry:
50+
enabled: true
51+
# Telemetry API URL. To send anonymous telemetry data, keep it default ("https://postgres.ai/api/general").
52+
url: "https://postgres.ai/api/general"
53+
4554
# Manages filesystem pools (in the case of ZFS) or volume groups.
4655
poolManager:
4756
# The full path which contains the pool mount directories. mountDir can contain multiple pool directories.

configs/config.example.physical_walg.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ global:
4242
# Default database name.
4343
dbname: postgres
4444

45+
# Telemetry: anonymous statistics sent to Postgres.ai.
46+
# Used to analyze DLE usage, it helps the DLE maintainers make decisions on product development.
47+
# Please leave it enabled if possible – this will contribute to DLE development.
48+
# The full list of data points being collected: https://postgres.ai/docs/database-lab/telemetry
49+
telemetry:
50+
enabled: true
51+
# Telemetry API URL. To send anonymous telemetry data, keep it default ("https://postgres.ai/api/general").
52+
url: "https://postgres.ai/api/general"
53+
4554
# Manages filesystem pools (in the case of ZFS) or volume groups.
4655
poolManager:
4756
# The full path which contains the pool mount directories. mountDir can contain multiple pool directories.

0 commit comments

Comments
 (0)