Avoid fission installation failure due to analytics connection error (#2457)

This commit is contained in:
Shubham Bansal
2022-06-15 11:32:06 +05:30
committed by GitHub
parent b80b41e1fd
commit 7f21b708e7
4 changed files with 168 additions and 18 deletions
+6 -1
View File
@@ -51,7 +51,12 @@ func eventCommandHandler(cmd *cobra.Command, args []string) error {
}
ctx := context.Background()
return tracker.Tracker.SendEvent(ctx, event)
t, err := tracker.NewTracker()
if err != nil {
return err
}
return t.SendEvent(ctx, event)
}
//EventCommand reports an event to analytics
+6 -2
View File
@@ -17,14 +17,18 @@ limitations under the License.
package main
import (
"log"
"go.uber.org/zap"
"github.com/fission/fission/cmd/reporter/app"
"github.com/fission/fission/pkg/utils/loggerfactory"
)
func main() {
logger := loggerfactory.GetLogger()
defer logger.Sync()
err := app.App().Execute()
if err != nil {
log.Fatal(err)
logger.Error("error occurred during analytics reporting", zap.Error(err))
}
}
+28 -14
View File
@@ -19,6 +19,7 @@ import (
"bytes"
"context"
"errors"
"fmt"
"net/http"
"net/url"
"os"
@@ -27,16 +28,17 @@ import (
uuid "github.com/satori/go.uuid"
)
const HTTP_TIMEOUT = 5 * time.Second
const GA_API_URL = "https://www.google-analytics.com/collect"
const GA_TRACKING_ID = "GA_TRACKING_ID"
var Tracker *tracker
const (
HTTP_TIMEOUT time.Duration = 5 * time.Second
GA_TRACKING_ID string = "GA_TRACKING_ID"
GA_API_URL string = "GA_API_URL"
)
type (
tracker struct {
Tracker struct {
gaPropertyID string
cid string
gaAPIURL string
}
Event struct {
Category string
@@ -46,19 +48,31 @@ type (
}
)
func init() {
func NewTracker() (*Tracker, error) {
id, err := uuid.NewV4()
if err != nil {
panic(err)
}
Tracker = &tracker{gaPropertyID: os.Getenv(GA_TRACKING_ID), cid: id.String()}
return nil, fmt.Errorf("tracker.NewTracker: error generating UUID: %w", err)
}
func (t *tracker) SendEvent(ctx context.Context, e Event) error {
if t.gaPropertyID == "" {
return errors.New("tracker.SendEvent: GA_TRACKING_ID env not set")
gaTrackingID := os.Getenv(GA_TRACKING_ID)
if gaTrackingID == "" {
return nil, errors.New("tracker.NewTracker: GA_TRACKING_ID env not set")
}
gaAPIURL := os.Getenv(GA_API_URL)
if gaAPIURL == "" {
gaAPIURL = "https://www.google-analytics.com/collect"
}
tracker := &Tracker{
gaPropertyID: gaTrackingID,
cid: id.String(),
gaAPIURL: gaAPIURL,
}
return tracker, nil
}
func (t *Tracker) SendEvent(ctx context.Context, e Event) error {
if e.Action == "" || e.Category == "" {
return errors.New("tracker.SendEvent: category and action are required")
}
@@ -81,7 +95,7 @@ func (t *tracker) SendEvent(ctx context.Context, e Event) error {
}
buf := bytes.NewBufferString(v.Encode())
req, err := http.NewRequestWithContext(ctx, "POST", GA_API_URL, buf)
req, err := http.NewRequestWithContext(ctx, "POST", t.gaAPIURL, buf)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("User-Agent", "ga-tracker/1.0")
if err != nil {
+127
View File
@@ -0,0 +1,127 @@
package tracker
import (
"context"
"encoding/json"
"errors"
"log"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestTracker(t *testing.T) {
t.Run("NewTracker", func(test *testing.T) {
for _, test := range []struct {
name string
gaAPIURl string
expected error
}{
{
name: "GA Tracking ID should not be empty",
gaAPIURl: "",
expected: errors.New("tracker.NewTracker: GA_TRACKING_ID env not set"),
},
{
name: "Tracker should initialize properly",
gaAPIURl: "/",
expected: nil,
},
} {
t.Run(test.name, func(testing *testing.T) {
if test.expected == nil {
os.Setenv(GA_TRACKING_ID, "UA-000000-2")
t, err := NewTracker()
assert.Nil(testing, err)
assert.NotNil(testing, t)
} else {
t, err := NewTracker()
assert.Nil(testing, t)
assert.NotNil(testing, err)
assert.Equal(testing, err.Error(), test.expected.Error())
}
})
}
})
t.Run("SendEvent", func(test *testing.T) {
os.Setenv(GA_TRACKING_ID, "UA-000000-2")
tr, err := NewTracker()
if err != nil {
log.Fatal(err)
}
for _, test := range []struct {
name string
request *Event
expected error
status int
}{
{
name: "category and action should not be empty",
request: &Event{
Category: "",
Action: "",
Label: "play",
Value: "value",
},
expected: errors.New("tracker.SendEvent: category and action are required"),
status: http.StatusInternalServerError,
},
{
name: "Google Analytics response should not be OK",
request: &Event{
Category: "UI_action",
Action: "button_press",
Label: "play",
Value: "value",
},
expected: errors.New("tracker.SendEvent: analytics response status not ok"),
status: http.StatusInternalServerError,
},
{
name: "Google Analytics response should be OK",
request: &Event{
Category: "UI_action",
Action: "button_press",
Label: "play",
Value: "value",
},
expected: nil,
status: http.StatusOK,
},
} {
t.Run(test.name, func(testing *testing.T) {
server := MockHTTPServer(test.status, "")
defer server.Close()
tr.gaAPIURL = server.URL
t := tr.SendEvent(context.Background(), *test.request)
if test.status == http.StatusOK {
assert.Nil(testing, t, test.expected)
} else {
assert.NotNil(testing, t)
assert.Equal(testing, t.Error(), test.expected.Error())
}
})
}
})
}
func MockHTTPServer(status int, encodeValue interface{}) *httptest.Server {
f := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(status)
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(encodeValue)
if err != nil {
log.Fatal(err)
}
}
return httptest.NewServer(http.HandlerFunc(f))
}