@@ -39,6 +39,7 @@ import (
39
39
"tailscale.com/types/key"
40
40
41
41
"cdr.dev/slog/sloggers/slogtest"
42
+ "github.com/coder/coder/v2/buildinfo"
42
43
"github.com/coder/coder/v2/cli"
43
44
"github.com/coder/coder/v2/cli/clitest"
44
45
"github.com/coder/coder/v2/cli/config"
@@ -947,36 +948,40 @@ func TestServer(t *testing.T) {
947
948
t .Run ("Telemetry" , func (t * testing.T ) {
948
949
t .Parallel ()
949
950
950
- deployment := make (chan struct {}, 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
- defer server .Close ()
951
+ telemetryServerURL , deployment , snapshot := mockTelemetryServer (t )
966
952
967
- inv , _ := clitest .New (t ,
953
+ inv , cfg := clitest .New (t ,
968
954
"server" ,
969
955
"--in-memory" ,
970
956
"--http-address" , ":0" ,
971
957
"--access-url" , "http://example.com" ,
972
958
"--telemetry" ,
973
- "--telemetry-url" , server . URL ,
959
+ "--telemetry-url" , telemetryServerURL . String () ,
974
960
"--cache-dir" , t .TempDir (),
975
961
)
976
962
clitest .Start (t , inv )
977
963
978
964
<- deployment
979
965
<- snapshot
966
+
967
+ accessURL := waitAccessURL (t , cfg )
968
+
969
+ ctx := testutil .Context (t , testutil .WaitMedium )
970
+ client := codersdk .New (accessURL )
971
+ body , err := client .Request (ctx , http .MethodGet , "/" , nil )
972
+ require .NoError (t , err )
973
+ require .NoError (t , body .Body .Close ())
974
+
975
+ require .Eventually (t , func () bool {
976
+ snap := <- snapshot
977
+ htmlFirstServedFound := false
978
+ for _ , item := range snap .TelemetryItems {
979
+ if item .Key == string (telemetry .TelemetryItemKeyHTMLFirstServedAt ) {
980
+ htmlFirstServedFound = true
981
+ }
982
+ }
983
+ return htmlFirstServedFound
984
+ }, testutil .WaitMedium , testutil .IntervalFast , "no html_first_served telemetry item" )
980
985
})
981
986
t .Run ("Prometheus" , func (t * testing.T ) {
982
987
t .Parallel ()
@@ -1990,3 +1995,148 @@ func TestServer_DisabledDERP(t *testing.T) {
1990
1995
err = c .Connect (ctx )
1991
1996
require .Error (t , err )
1992
1997
}
1998
+
1999
+ type runServerOpts struct {
2000
+ waitForSnapshot bool
2001
+ telemetryDisabled bool
2002
+ waitForTelemetryDisabledCheck bool
2003
+ }
2004
+
2005
+ func TestServer_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 , opts runServerOpts ) (chan error , 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 (chan bool , 2 )
2030
+ errChan := make (chan error , 1 )
2031
+ pty := ptytest .New (t ).Attach (inv )
2032
+ go func () {
2033
+ errChan <- inv .WithContext (ctx ).Run ()
2034
+ finished <- true
2035
+ }()
2036
+ go func () {
2037
+ defer func () {
2038
+ finished <- true
2039
+ }()
2040
+ if opts .waitForSnapshot {
2041
+ pty .ExpectMatchContext (testutil .Context (t , testutil .WaitLong ), "submitted snapshot" )
2042
+ }
2043
+ if opts .waitForTelemetryDisabledCheck {
2044
+ pty .ExpectMatchContext (testutil .Context (t , testutil .WaitLong ), "finished telemetry status check" )
2045
+ }
2046
+ }()
2047
+ <- finished
2048
+ return errChan , cancelFunc
2049
+ }
2050
+ waitForShutdown := func (t * testing.T , errChan chan error ) error {
2051
+ t .Helper ()
2052
+ select {
2053
+ case err := <- errChan :
2054
+ return err
2055
+ case <- time .After (testutil .WaitMedium ):
2056
+ t .Fatalf ("timed out waiting for server to shutdown" )
2057
+ }
2058
+ return nil
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
+ for i := 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
+ case ss := <- 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
+ func mockTelemetryServer (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
+ return serverURL , deployment , snapshot
2142
+ }
0 commit comments