mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
Add UI telemetry (#6981)
* Load Segment module * First events * Add GET /telemetry epoint to API * Init telemetry with data from API * Add more tracking * Update ui static files * Send telemetry for tab changes * Update UI static files * Set IP to 0.0.0.0 * Update UI static files
This commit is contained in:
1
pkg/apiserver-gen/.openapi-generator/FILES
generated
1
pkg/apiserver-gen/.openapi-generator/FILES
generated
@@ -37,4 +37,5 @@ go/model_image_command.go
|
||||
go/model_metadata.go
|
||||
go/model_metadata_request.go
|
||||
go/model_resource.go
|
||||
go/model_telemetry_response.go
|
||||
go/routers.go
|
||||
|
||||
2
pkg/apiserver-gen/go/api.go
generated
2
pkg/apiserver-gen/go/api.go
generated
@@ -44,6 +44,7 @@ type DefaultApiRouter interface {
|
||||
DevstateResourceResourceNameDelete(http.ResponseWriter, *http.Request)
|
||||
InstanceDelete(http.ResponseWriter, *http.Request)
|
||||
InstanceGet(http.ResponseWriter, *http.Request)
|
||||
TelemetryGet(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
// DefaultApiServicer defines the api actions for the DefaultApi service
|
||||
@@ -77,4 +78,5 @@ type DefaultApiServicer interface {
|
||||
DevstateResourceResourceNameDelete(context.Context, string) (ImplResponse, error)
|
||||
InstanceDelete(context.Context) (ImplResponse, error)
|
||||
InstanceGet(context.Context) (ImplResponse, error)
|
||||
TelemetryGet(context.Context) (ImplResponse, error)
|
||||
}
|
||||
|
||||
19
pkg/apiserver-gen/go/api_default.go
generated
19
pkg/apiserver-gen/go/api_default.go
generated
@@ -206,6 +206,12 @@ func (c *DefaultApiController) Routes() Routes {
|
||||
"/api/v1/instance",
|
||||
c.InstanceGet,
|
||||
},
|
||||
{
|
||||
"TelemetryGet",
|
||||
strings.ToUpper("Get"),
|
||||
"/api/v1/telemetry",
|
||||
c.TelemetryGet,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,3 +720,16 @@ func (c *DefaultApiController) InstanceGet(w http.ResponseWriter, r *http.Reques
|
||||
EncodeJSONResponse(result.Body, &result.Code, w)
|
||||
|
||||
}
|
||||
|
||||
// TelemetryGet -
|
||||
func (c *DefaultApiController) TelemetryGet(w http.ResponseWriter, r *http.Request) {
|
||||
result, err := c.service.TelemetryGet(r.Context())
|
||||
// If an error occurred, encode the error with the status code
|
||||
if err != nil {
|
||||
c.errorHandler(w, r, err, &result)
|
||||
return
|
||||
}
|
||||
// If no error, encode the body and the result code
|
||||
EncodeJSONResponse(result.Body, &result.Code, w)
|
||||
|
||||
}
|
||||
|
||||
44
pkg/apiserver-gen/go/model__telemetry_get_200_response.go
generated
Normal file
44
pkg/apiserver-gen/go/model__telemetry_get_200_response.go
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* odo dev
|
||||
*
|
||||
* API interface for 'odo dev'
|
||||
*
|
||||
* API version: 0.1
|
||||
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||
*/
|
||||
|
||||
package openapi
|
||||
|
||||
type TelemetryGet200Response struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
Apikey string `json:"apikey,omitempty"`
|
||||
|
||||
Userid string `json:"userid,omitempty"`
|
||||
}
|
||||
|
||||
// AssertTelemetryGet200ResponseRequired checks if the required fields are not zero-ed
|
||||
func AssertTelemetryGet200ResponseRequired(obj TelemetryGet200Response) error {
|
||||
elements := map[string]interface{}{
|
||||
"enabled": obj.Enabled,
|
||||
}
|
||||
for name, el := range elements {
|
||||
if isZero := IsZeroValue(el); isZero {
|
||||
return &RequiredError{Field: name}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseTelemetryGet200ResponseRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of TelemetryGet200Response (e.g. [][]TelemetryGet200Response), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseTelemetryGet200ResponseRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aTelemetryGet200Response, ok := obj.(TelemetryGet200Response)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertTelemetryGet200ResponseRequired(aTelemetryGet200Response)
|
||||
})
|
||||
}
|
||||
44
pkg/apiserver-gen/go/model_telemetry_response.go
generated
Normal file
44
pkg/apiserver-gen/go/model_telemetry_response.go
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* odo dev
|
||||
*
|
||||
* API interface for 'odo dev'
|
||||
*
|
||||
* API version: 0.1
|
||||
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||
*/
|
||||
|
||||
package openapi
|
||||
|
||||
type TelemetryResponse struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
Apikey string `json:"apikey,omitempty"`
|
||||
|
||||
Userid string `json:"userid,omitempty"`
|
||||
}
|
||||
|
||||
// AssertTelemetryResponseRequired checks if the required fields are not zero-ed
|
||||
func AssertTelemetryResponseRequired(obj TelemetryResponse) error {
|
||||
elements := map[string]interface{}{
|
||||
"enabled": obj.Enabled,
|
||||
}
|
||||
for name, el := range elements {
|
||||
if isZero := IsZeroValue(el); isZero {
|
||||
return &RequiredError{Field: name}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertRecurseTelemetryResponseRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||
// Accepts only nested slice of TelemetryResponse (e.g. [][]TelemetryResponse), otherwise ErrTypeAssertionError is thrown.
|
||||
func AssertRecurseTelemetryResponseRequired(objSlice interface{}) error {
|
||||
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||
aTelemetryResponse, ok := obj.(TelemetryResponse)
|
||||
if !ok {
|
||||
return ErrTypeAssertionError
|
||||
}
|
||||
return AssertTelemetryResponseRequired(aTelemetryResponse)
|
||||
})
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
odocontext "github.com/redhat-developer/odo/pkg/odo/context"
|
||||
"github.com/redhat-developer/odo/pkg/podman"
|
||||
"github.com/redhat-developer/odo/pkg/preference"
|
||||
"github.com/redhat-developer/odo/pkg/segment"
|
||||
scontext "github.com/redhat-developer/odo/pkg/segment/context"
|
||||
"github.com/redhat-developer/odo/pkg/state"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
@@ -175,3 +177,27 @@ func (s *DefaultApiService) validateDevfile(ctx context.Context, dir string) err
|
||||
}
|
||||
return validate.ValidateDevfileData(devObj.Data)
|
||||
}
|
||||
|
||||
func (s *DefaultApiService) TelemetryGet(ctx context.Context) (openapi.ImplResponse, error) {
|
||||
var (
|
||||
enabled = scontext.GetTelemetryStatus(ctx)
|
||||
apikey string
|
||||
userid string
|
||||
)
|
||||
if enabled {
|
||||
apikey = segment.GetApikey()
|
||||
var err error
|
||||
userid, err = segment.GetUserIdentity(segment.GetTelemetryFilePath())
|
||||
if err != nil {
|
||||
return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
|
||||
Message: fmt.Sprintf("error getting telemetry data: %s", err),
|
||||
}), nil
|
||||
}
|
||||
}
|
||||
|
||||
return openapi.Response(http.StatusOK, openapi.TelemetryResponse{
|
||||
Enabled: enabled,
|
||||
Apikey: apikey,
|
||||
Userid: userid,
|
||||
}), nil
|
||||
}
|
||||
|
||||
3
pkg/apiserver-impl/ui/3rdpartylicenses.txt
generated
3
pkg/apiserver-impl/ui/3rdpartylicenses.txt
generated
@@ -1321,6 +1321,9 @@ terms above.
|
||||
mermaid
|
||||
MIT
|
||||
|
||||
ngx-segment-analytics
|
||||
MIT
|
||||
|
||||
rxjs
|
||||
Apache-2.0
|
||||
Apache License
|
||||
|
||||
2
pkg/apiserver-impl/ui/index.html
generated
2
pkg/apiserver-impl/ui/index.html
generated
@@ -11,6 +11,6 @@
|
||||
<body class="mat-typography">
|
||||
<div id="loading">Loading, please wait...</div>
|
||||
<app-root></app-root>
|
||||
<script src="runtime.1289ea0acffcdc5e.js" type="module"></script><script src="polyfills.8b3b37cedaf377c3.js" type="module"></script><script src="main.2ab96df0533a01ab.js" type="module"></script>
|
||||
<script src="runtime.1289ea0acffcdc5e.js" type="module"></script><script src="polyfills.8b3b37cedaf377c3.js" type="module"></script><script src="main.64f53365507b1341.js" type="module"></script>
|
||||
|
||||
</body></html>
|
||||
1
pkg/apiserver-impl/ui/main.2ab96df0533a01ab.js
generated
1
pkg/apiserver-impl/ui/main.2ab96df0533a01ab.js
generated
File diff suppressed because one or more lines are too long
1
pkg/apiserver-impl/ui/main.64f53365507b1341.js
generated
Normal file
1
pkg/apiserver-impl/ui/main.64f53365507b1341.js
generated
Normal file
File diff suppressed because one or more lines are too long
@@ -155,6 +155,9 @@ func GenericRun(o Runnable, testClientset clientset.Clientset, cmd *cobra.Comman
|
||||
klog.V(4).Infof("WARNING: debug telemetry, if enabled, will be logged in %s", debugTelemetry)
|
||||
}
|
||||
|
||||
isTelemetryEnabled := segment.IsTelemetryEnabled(userConfig, envcontext.GetEnvConfig(ctx))
|
||||
scontext.SetTelemetryStatus(ctx, isTelemetryEnabled)
|
||||
|
||||
// We can dereference as there is a default value defined for this config field
|
||||
err = scontext.SetCaller(ctx, envConfig.TelemetryCaller)
|
||||
if err != nil {
|
||||
|
||||
@@ -39,7 +39,7 @@ func getTelemetryForDevfileRegistry(ctx context.Context) (registryLibrary.Teleme
|
||||
tag, _ := locale.Detect()
|
||||
td.Locale = tag.String()
|
||||
|
||||
user, err := getUserIdentity(GetTelemetryFilePath())
|
||||
user, err := GetUserIdentity(GetTelemetryFilePath())
|
||||
if err != nil {
|
||||
// default to the generic user ID if the anonymous ID cannot be found
|
||||
td.User = td.Client
|
||||
|
||||
@@ -73,6 +73,10 @@ type Client struct {
|
||||
TelemetryFilePath string
|
||||
}
|
||||
|
||||
func GetApikey() string {
|
||||
return writeKey
|
||||
}
|
||||
|
||||
// NewClient returns a Client created with the default args
|
||||
func NewClient() (*Client, error) {
|
||||
return newCustomClient(
|
||||
@@ -131,7 +135,7 @@ func (c *Client) Upload(ctx context.Context, data TelemetryData) error {
|
||||
}
|
||||
|
||||
// obtain the user ID
|
||||
userId, uerr := getUserIdentity(c.TelemetryFilePath)
|
||||
userId, uerr := GetUserIdentity(c.TelemetryFilePath)
|
||||
if uerr != nil {
|
||||
return uerr
|
||||
}
|
||||
@@ -193,8 +197,8 @@ func GetTelemetryFilePath() string {
|
||||
return filepath.Join(homeDir, ".redhat", "anonymousId")
|
||||
}
|
||||
|
||||
// getUserIdentity returns the anonymous ID if it exists, else creates a new one and sends the data to Segment
|
||||
func getUserIdentity(telemetryFilePath string) (string, error) {
|
||||
// GetUserIdentity returns the anonymous ID if it exists, else creates a new one and sends the data to Segment
|
||||
func GetUserIdentity(telemetryFilePath string) (string, error) {
|
||||
var id []byte
|
||||
|
||||
// Get-or-Create the '$HOME/.redhat' directory
|
||||
|
||||
Reference in New Issue
Block a user