Avoid fission installation failure due to analytics connection error (#2457)
This commit is contained in:
@@ -51,7 +51,12 @@ func eventCommandHandler(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
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
|
//EventCommand reports an event to analytics
|
||||||
|
|||||||
@@ -17,14 +17,18 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/fission/fission/cmd/reporter/app"
|
"github.com/fission/fission/cmd/reporter/app"
|
||||||
|
"github.com/fission/fission/pkg/utils/loggerfactory"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
logger := loggerfactory.GetLogger()
|
||||||
|
defer logger.Sync()
|
||||||
|
|
||||||
err := app.App().Execute()
|
err := app.App().Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
logger.Error("error occurred during analytics reporting", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-15
@@ -19,6 +19,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@@ -27,16 +28,17 @@ import (
|
|||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
const HTTP_TIMEOUT = 5 * time.Second
|
const (
|
||||||
const GA_API_URL = "https://www.google-analytics.com/collect"
|
HTTP_TIMEOUT time.Duration = 5 * time.Second
|
||||||
const GA_TRACKING_ID = "GA_TRACKING_ID"
|
GA_TRACKING_ID string = "GA_TRACKING_ID"
|
||||||
|
GA_API_URL string = "GA_API_URL"
|
||||||
var Tracker *tracker
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
tracker struct {
|
Tracker struct {
|
||||||
gaPropertyID string
|
gaPropertyID string
|
||||||
cid string
|
cid string
|
||||||
|
gaAPIURL string
|
||||||
}
|
}
|
||||||
Event struct {
|
Event struct {
|
||||||
Category string
|
Category string
|
||||||
@@ -46,19 +48,31 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func NewTracker() (*Tracker, error) {
|
||||||
id, err := uuid.NewV4()
|
id, err := uuid.NewV4()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, fmt.Errorf("tracker.NewTracker: error generating UUID: %w", err)
|
||||||
}
|
}
|
||||||
Tracker = &tracker{gaPropertyID: os.Getenv(GA_TRACKING_ID), cid: id.String()}
|
|
||||||
|
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 {
|
func (t *Tracker) SendEvent(ctx context.Context, e Event) error {
|
||||||
if t.gaPropertyID == "" {
|
|
||||||
return errors.New("tracker.SendEvent: GA_TRACKING_ID env not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.Action == "" || e.Category == "" {
|
if e.Action == "" || e.Category == "" {
|
||||||
return errors.New("tracker.SendEvent: category and action are required")
|
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())
|
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("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.Header.Add("User-Agent", "ga-tracker/1.0")
|
req.Header.Add("User-Agent", "ga-tracker/1.0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -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))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user