Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita68d115

Browse files
authored
chore: track disabled telemetry (#16347)
Addressescoder/nexus#116.## Core ConceptSend one final telemetry report after the user disables telemetry withthe message that the telemetry was disabled. No other information aboutthe deployment is sent in this report.This final report is submitted only if the deployment ever had telemetryon.## Changes1. Refactored how our telemetry is initialized.2. Introduced the `TelemetryEnabled` telemetry item, which allows todecide whether a final report should be sent.3. Added the `RecordTelemetryStatus` telemetry method, which decideswhether a final report should be sent and updates the telemetry item.4. Added tests to ensure the implementation is correct.
1 parent286b3d2 commita68d115

File tree

4 files changed

+352
-63
lines changed

4 files changed

+352
-63
lines changed

‎cli/server.go

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -781,40 +781,42 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
781781
// This should be output before the logs start streaming.
782782
cliui.Infof(inv.Stdout,"\n==> Logs will stream in below (press ctrl+c to gracefully exit):")
783783

784-
ifvals.Telemetry.Enable {
785-
vals,err:=vals.WithoutSecrets()
786-
iferr!=nil {
787-
returnxerrors.Errorf("remove secrets from deployment values: %w",err)
788-
}
789-
options.Telemetry,err=telemetry.New(telemetry.Options{
790-
BuiltinPostgres:builtinPostgres,
791-
DeploymentID:deploymentID,
792-
Database:options.Database,
793-
Logger:logger.Named("telemetry"),
794-
URL:vals.Telemetry.URL.Value(),
795-
Tunnel:tunnel!=nil,
796-
DeploymentConfig:vals,
797-
ParseLicenseJWT:func(lic*telemetry.License)error {
798-
// This will be nil when running in AGPL-only mode.
799-
ifoptions.ParseLicenseClaims==nil {
800-
returnnil
801-
}
802-
803-
email,trial,err:=options.ParseLicenseClaims(lic.JWT)
804-
iferr!=nil {
805-
returnerr
806-
}
807-
ifemail!="" {
808-
lic.Email=&email
809-
}
810-
lic.Trial=&trial
784+
deploymentConfigWithoutSecrets,err:=vals.WithoutSecrets()
785+
iferr!=nil {
786+
returnxerrors.Errorf("remove secrets from deployment values: %w",err)
787+
}
788+
telemetryReporter,err:=telemetry.New(telemetry.Options{
789+
Disabled:!vals.Telemetry.Enable.Value(),
790+
BuiltinPostgres:builtinPostgres,
791+
DeploymentID:deploymentID,
792+
Database:options.Database,
793+
Logger:logger.Named("telemetry"),
794+
URL:vals.Telemetry.URL.Value(),
795+
Tunnel:tunnel!=nil,
796+
DeploymentConfig:deploymentConfigWithoutSecrets,
797+
ParseLicenseJWT:func(lic*telemetry.License)error {
798+
// This will be nil when running in AGPL-only mode.
799+
ifoptions.ParseLicenseClaims==nil {
811800
returnnil
812-
},
813-
})
814-
iferr!=nil {
815-
returnxerrors.Errorf("create telemetry reporter: %w",err)
816-
}
817-
deferoptions.Telemetry.Close()
801+
}
802+
803+
email,trial,err:=options.ParseLicenseClaims(lic.JWT)
804+
iferr!=nil {
805+
returnerr
806+
}
807+
ifemail!="" {
808+
lic.Email=&email
809+
}
810+
lic.Trial=&trial
811+
returnnil
812+
},
813+
})
814+
iferr!=nil {
815+
returnxerrors.Errorf("create telemetry reporter: %w",err)
816+
}
817+
defertelemetryReporter.Close()
818+
ifvals.Telemetry.Enable.Value() {
819+
options.Telemetry=telemetryReporter
818820
}else {
819821
logger.Warn(ctx,fmt.Sprintf(`telemetry disabled, unable to notify of security issues. Read more: %s/admin/setup/telemetry`,vals.DocsURL.String()))
820822
}

‎cli/server_test.go

Lines changed: 148 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"tailscale.com/types/key"
4040

4141
"cdr.dev/slog/sloggers/slogtest"
42+
"github.com/coder/coder/v2/buildinfo"
4243
"github.com/coder/coder/v2/cli"
4344
"github.com/coder/coder/v2/cli/clitest"
4445
"github.com/coder/coder/v2/cli/config"
@@ -947,30 +948,15 @@ func TestServer(t *testing.T) {
947948
t.Run("Telemetry",func(t*testing.T) {
948949
t.Parallel()
949950

950-
deployment:=make(chanstruct{},64)
951-
snapshot:=make(chan*telemetry.Snapshot,64)
952-
r:=chi.NewRouter()
953-
r.Post("/deployment",func(w http.ResponseWriter,r*http.Request) {
954-
w.WriteHeader(http.StatusAccepted)
955-
deployment<-struct{}{}
956-
})
957-
r.Post("/snapshot",func(w http.ResponseWriter,r*http.Request) {
958-
w.WriteHeader(http.StatusAccepted)
959-
ss:=&telemetry.Snapshot{}
960-
err:=json.NewDecoder(r.Body).Decode(ss)
961-
require.NoError(t,err)
962-
snapshot<-ss
963-
})
964-
server:=httptest.NewServer(r)
965-
deferserver.Close()
951+
telemetryServerURL,deployment,snapshot:=mockTelemetryServer(t)
966952

967953
inv,cfg:=clitest.New(t,
968954
"server",
969955
"--in-memory",
970956
"--http-address",":0",
971957
"--access-url","http://example.com",
972958
"--telemetry",
973-
"--telemetry-url",server.URL,
959+
"--telemetry-url",telemetryServerURL.String(),
974960
"--cache-dir",t.TempDir(),
975961
)
976962
clitest.Start(t,inv)
@@ -2009,3 +1995,148 @@ func TestServer_DisabledDERP(t *testing.T) {
20091995
err=c.Connect(ctx)
20101996
require.Error(t,err)
20111997
}
1998+
1999+
typerunServerOptsstruct {
2000+
waitForSnapshotbool
2001+
telemetryDisabledbool
2002+
waitForTelemetryDisabledCheckbool
2003+
}
2004+
2005+
funcTestServer_TelemetryDisabled_FinalReport(t*testing.T) {
2006+
t.Parallel()
2007+
2008+
if!dbtestutil.WillUsePostgres() {
2009+
t.Skip("this test requires postgres")
2010+
}
2011+
2012+
telemetryServerURL,deployment,snapshot:=mockTelemetryServer(t)
2013+
dbConnURL,err:=dbtestutil.Open(t)
2014+
require.NoError(t,err)
2015+
2016+
cacheDir:=t.TempDir()
2017+
runServer:=func(t*testing.T,optsrunServerOpts) (chanerror, context.CancelFunc) {
2018+
ctx,cancelFunc:=context.WithCancel(context.Background())
2019+
inv,_:=clitest.New(t,
2020+
"server",
2021+
"--postgres-url",dbConnURL,
2022+
"--http-address",":0",
2023+
"--access-url","http://example.com",
2024+
"--telemetry="+strconv.FormatBool(!opts.telemetryDisabled),
2025+
"--telemetry-url",telemetryServerURL.String(),
2026+
"--cache-dir",cacheDir,
2027+
"--log-filter",".*",
2028+
)
2029+
finished:=make(chanbool,2)
2030+
errChan:=make(chanerror,1)
2031+
pty:=ptytest.New(t).Attach(inv)
2032+
gofunc() {
2033+
errChan<-inv.WithContext(ctx).Run()
2034+
finished<-true
2035+
}()
2036+
gofunc() {
2037+
deferfunc() {
2038+
finished<-true
2039+
}()
2040+
ifopts.waitForSnapshot {
2041+
pty.ExpectMatchContext(testutil.Context(t,testutil.WaitLong),"submitted snapshot")
2042+
}
2043+
ifopts.waitForTelemetryDisabledCheck {
2044+
pty.ExpectMatchContext(testutil.Context(t,testutil.WaitLong),"finished telemetry status check")
2045+
}
2046+
}()
2047+
<-finished
2048+
returnerrChan,cancelFunc
2049+
}
2050+
waitForShutdown:=func(t*testing.T,errChanchanerror)error {
2051+
t.Helper()
2052+
select {
2053+
caseerr:=<-errChan:
2054+
returnerr
2055+
case<-time.After(testutil.WaitMedium):
2056+
t.Fatalf("timed out waiting for server to shutdown")
2057+
}
2058+
returnnil
2059+
}
2060+
2061+
errChan,cancelFunc:=runServer(t,runServerOpts{telemetryDisabled:true,waitForTelemetryDisabledCheck:true})
2062+
cancelFunc()
2063+
require.NoError(t,waitForShutdown(t,errChan))
2064+
2065+
// Since telemetry was disabled, we expect no deployments or snapshots.
2066+
require.Empty(t,deployment)
2067+
require.Empty(t,snapshot)
2068+
2069+
errChan,cancelFunc=runServer(t,runServerOpts{waitForSnapshot:true})
2070+
cancelFunc()
2071+
require.NoError(t,waitForShutdown(t,errChan))
2072+
// we expect to see a deployment and a snapshot twice:
2073+
// 1. the first pair is sent when the server starts
2074+
// 2. the second pair is sent when the server shuts down
2075+
fori:=0;i<2;i++ {
2076+
select {
2077+
case<-snapshot:
2078+
case<-time.After(testutil.WaitShort/2):
2079+
t.Fatalf("timed out waiting for snapshot")
2080+
}
2081+
select {
2082+
case<-deployment:
2083+
case<-time.After(testutil.WaitShort/2):
2084+
t.Fatalf("timed out waiting for deployment")
2085+
}
2086+
}
2087+
2088+
errChan,cancelFunc=runServer(t,runServerOpts{telemetryDisabled:true,waitForTelemetryDisabledCheck:true})
2089+
cancelFunc()
2090+
require.NoError(t,waitForShutdown(t,errChan))
2091+
2092+
// Since telemetry is disabled, we expect no deployment. We expect a snapshot
2093+
// with the telemetry disabled item.
2094+
require.Empty(t,deployment)
2095+
select {
2096+
casess:=<-snapshot:
2097+
require.Len(t,ss.TelemetryItems,1)
2098+
require.Equal(t,string(telemetry.TelemetryItemKeyTelemetryEnabled),ss.TelemetryItems[0].Key)
2099+
require.Equal(t,"false",ss.TelemetryItems[0].Value)
2100+
case<-time.After(testutil.WaitShort/2):
2101+
t.Fatalf("timed out waiting for snapshot")
2102+
}
2103+
2104+
errChan,cancelFunc=runServer(t,runServerOpts{telemetryDisabled:true,waitForTelemetryDisabledCheck:true})
2105+
cancelFunc()
2106+
require.NoError(t,waitForShutdown(t,errChan))
2107+
// Since telemetry is disabled and we've already sent a snapshot, we expect no
2108+
// new deployments or snapshots.
2109+
require.Empty(t,deployment)
2110+
require.Empty(t,snapshot)
2111+
}
2112+
2113+
funcmockTelemetryServer(t*testing.T) (*url.URL,chan*telemetry.Deployment,chan*telemetry.Snapshot) {
2114+
t.Helper()
2115+
deployment:=make(chan*telemetry.Deployment,64)
2116+
snapshot:=make(chan*telemetry.Snapshot,64)
2117+
r:=chi.NewRouter()
2118+
r.Post("/deployment",func(w http.ResponseWriter,r*http.Request) {
2119+
require.Equal(t,buildinfo.Version(),r.Header.Get(telemetry.VersionHeader))
2120+
dd:=&telemetry.Deployment{}
2121+
err:=json.NewDecoder(r.Body).Decode(dd)
2122+
require.NoError(t,err)
2123+
deployment<-dd
2124+
// Ensure the header is sent only after deployment is sent
2125+
w.WriteHeader(http.StatusAccepted)
2126+
})
2127+
r.Post("/snapshot",func(w http.ResponseWriter,r*http.Request) {
2128+
require.Equal(t,buildinfo.Version(),r.Header.Get(telemetry.VersionHeader))
2129+
ss:=&telemetry.Snapshot{}
2130+
err:=json.NewDecoder(r.Body).Decode(ss)
2131+
require.NoError(t,err)
2132+
snapshot<-ss
2133+
// Ensure the header is sent only after snapshot is sent
2134+
w.WriteHeader(http.StatusAccepted)
2135+
})
2136+
server:=httptest.NewServer(r)
2137+
t.Cleanup(server.Close)
2138+
serverURL,err:=url.Parse(server.URL)
2139+
require.NoError(t,err)
2140+
2141+
returnserverURL,deployment,snapshot
2142+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp