Commit 9bdf85b6 authored by Andrei Mihu's avatar Andrei Mihu
Browse files

Update dependencies.

parent cf050705
Loading
Loading
Loading
Loading
+28 −29
Original line number Diff line number Diff line
@@ -9,14 +9,14 @@
    "monitoring/apiv3",
    "trace/apiv2"
  ]
  revision = "20d4028b8a750c2aca76bf9fefa8ed2d0109b573"
  version = "v0.19.0"
  revision = "4b98a6370e36d7a85192e7bad08a4ebd82eac2a8"
  version = "v0.20.0"

[[projects]]
  branch = "master"
  name = "github.com/beorn7/perks"
  packages = ["quantile"]
  revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9"
  revision = "3a771d992973f24aa725d07868b467d1ddfceafb"

[[projects]]
  name = "github.com/davecgh/go-spew"
@@ -33,12 +33,13 @@
[[projects]]
  name = "github.com/go-yaml/yaml"
  packages = ["."]
  revision = "c95af922eae69f190717a0b7148960af8c55a072"
  revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"

[[projects]]
  name = "github.com/gobuffalo/packr"
  packages = ["."]
  revision = "6434a292ac52e6964adebfdce3f9ce6d9f16be01"
  revision = "3402a167bccf1bdd5c93ca820be9f27bba46261e"
  version = "v1.10.7"

[[projects]]
  name = "github.com/golang/protobuf"
@@ -89,7 +90,7 @@
[[projects]]
  name = "github.com/gorilla/websocket"
  packages = ["."]
  revision = "292fd08b2560ad524ee37396253d71570339a821"
  revision = "eb925808374e5ca90c83401a40d711dc08c0c0f6"

[[projects]]
  name = "github.com/grpc-ecosystem/grpc-gateway"
@@ -108,7 +109,7 @@
    ".",
    "oid"
  ]
  revision = "83612a56d3dd153a94a629cd64925371c9adad78"
  revision = "d34b9ff171c21ad295489235aec8b6626023cd04"

[[projects]]
  name = "github.com/matttproud/golang_protobuf_extensions"
@@ -150,7 +151,7 @@
    "internal/bitbucket.org/ww/goautoneg",
    "model"
  ]
  revision = "e4aa40a9169a88835b849a6efb71e05dc04b88f0"
  revision = "38c53a9f4bfcd932d1b00bfc65e256a7fba6b37a"

[[projects]]
  branch = "master"
@@ -161,7 +162,7 @@
    "nfs",
    "xfs"
  ]
  revision = "54d17b57dd7d4a3aa092476596b3f8a933bde349"
  revision = "780932d4fbbe0e69b84c34c20f5c8d0981e109ea"

[[projects]]
  name = "github.com/rubenv/sql-migrate"
@@ -169,18 +170,18 @@
    ".",
    "sqlparse"
  ]
  revision = "6edbfbd6a369ee82463312ec67b2c92f97a1d4dc"
  revision = "081fe17d19ff4e2dd9f5a0c1158e6bcf74da6906"

[[projects]]
  name = "github.com/satori/go.uuid"
  packages = ["."]
  revision = "063359185d32c6b045fa171ad7033ea545864fa1"
  revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e"

[[projects]]
  name = "github.com/stretchr/testify"
  packages = ["assert"]
  revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0"
  version = "v1.1.4"
  revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
  version = "v1.2.1"

[[projects]]
  name = "github.com/yuin/gopher-lua"
@@ -190,30 +191,28 @@
    "parse",
    "pm"
  ]
  revision = "7d7bc8747e3f614c5c587729a341fe7d8903cdb8"
  revision = "84ea3a3c79b3c4b3b39606cc96f255cd63635ce0"

[[projects]]
  name = "go.opencensus.io"
  packages = [
    "exporter/prometheus",
    "exporter/stackdriver",
    "exporter/stackdriver/propagation",
    "internal",
    "internal/tagencoding",
    "plugin/ocgrpc",
    "plugin/ochttp",
    "plugin/ochttp/propagation/b3",
    "plugin/ochttp/propagation/google",
    "stats",
    "stats/internal",
    "stats/view",
    "tag",
    "trace",
    "trace/propagation",
    "zpages",
    "zpages/internal"
    "trace/propagation"
  ]
  revision = "983446b8dae3871316dc8610f7aa61e160b50b31"
  version = "v0.5.0"
  revision = "6e3f034057826b530038d93267906ec3c012183f"
  version = "v0.6.0"

[[projects]]
  name = "go.uber.org/atomic"
@@ -246,7 +245,7 @@
    "bcrypt",
    "blowfish"
  ]
  revision = "1875d0a70c90e57f11972aefd42276df65e895b9"
  revision = "88942b9c40a4c9d203b82b3731787b672d6e809b"

[[projects]]
  branch = "master"
@@ -261,7 +260,7 @@
    "lex/httplex",
    "trace"
  ]
  revision = "2fb46b16b8dda405028c50f7c7f0f9dd1fa6bfb1"
  revision = "6078986fec03a1dcc236c34816c71b0e05018fda"

[[projects]]
  branch = "master"
@@ -282,7 +281,6 @@
  revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"

[[projects]]
  branch = "master"
  name = "golang.org/x/text"
  packages = [
    "collate",
@@ -300,7 +298,8 @@
    "unicode/norm",
    "unicode/rangetable"
  ]
  revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3"
  revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
  version = "v0.3.0"

[[projects]]
  branch = "master"
@@ -315,7 +314,7 @@
    "transport/grpc",
    "transport/http"
  ]
  revision = "55e9fb4044f4757138d4273ace23060d022d18f9"
  revision = "dbbc13f71100fa6ece308335445fca6bb0dd5c2f"

[[projects]]
  name = "google.golang.org/appengine"
@@ -350,7 +349,7 @@
    "googleapis/rpc/status",
    "protobuf/field_mask"
  ]
  revision = "4eb30f4778eed4c258ba66527a0d4f9ec8a36c45"
  revision = "ab0870e398d5dd054b868c0db1481ab029b9a9f2"

[[projects]]
  name = "google.golang.org/grpc"
@@ -381,8 +380,8 @@
    "tap",
    "transport"
  ]
  revision = "8e4536a86ab602859c20df5ebfd0bd4228d08655"
  version = "v1.10.0"
  revision = "1e2570b1b19ade82d8dbb31bba4e65e9f9ef5b34"
  version = "v1.11.1"

[[projects]]
  name = "gopkg.in/gorp.v1"
@@ -393,6 +392,6 @@
[solve-meta]
  analyzer-name = "dep"
  analyzer-version = 1
  inputs-digest = "d34f7dd83d8d4cdaa558556d02455ac16c463f0e61afdd76ecce2729e2486235"
  inputs-digest = "c9cf37873849b7c9ea30ef66151a1540afde6e0a518de051f8aef425e2e92f77"
  solver-name = "gps-cdcl"
  solver-version = 1
+10 −10
Original line number Diff line number Diff line
@@ -4,23 +4,23 @@

[[constraint]]
  name = "google.golang.org/grpc"
  version = "~1.10.0"
  version = "~1.11.1"

[[constraint]]
  name = "github.com/go-yaml/yaml"
  revision = "c95af922eae69f190717a0b7148960af8c55a072"
  revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"

[[constraint]]
  name = "github.com/satori/go.uuid"
  revision = "063359185d32c6b045fa171ad7033ea545864fa1"
  revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e"

[[constraint]]
  name = "github.com/rubenv/sql-migrate"
  revision = "6edbfbd6a369ee82463312ec67b2c92f97a1d4dc"
  revision = "081fe17d19ff4e2dd9f5a0c1158e6bcf74da6906"

[[constraint]]
  name = "github.com/lib/pq"
  revision = "83612a56d3dd153a94a629cd64925371c9adad78"
  revision = "d34b9ff171c21ad295489235aec8b6626023cd04"

[[constraint]]
  name = "github.com/gorilla/handlers"
@@ -36,11 +36,11 @@

[[constraint]]
  name = "github.com/gorilla/websocket"
  revision = "292fd08b2560ad524ee37396253d71570339a821"
  revision = "eb925808374e5ca90c83401a40d711dc08c0c0f6"

[[constraint]]
  name = "github.com/yuin/gopher-lua"
  revision = "7d7bc8747e3f614c5c587729a341fe7d8903cdb8"
  revision = "84ea3a3c79b3c4b3b39606cc96f255cd63635ce0"

[[constraint]]
  name = "github.com/gorhill/cronexpr"
@@ -48,11 +48,11 @@

[[constraint]]
  name = "golang.org/x/crypto"
  revision = "1875d0a70c90e57f11972aefd42276df65e895b9"
  revision = "88942b9c40a4c9d203b82b3731787b672d6e809b"

[[constraint]]
  name = "github.com/gobuffalo/packr"
  revision = "6434a292ac52e6964adebfdce3f9ce6d9f16be01"
  version = "~1.10.7"

[[override]]
  name = "github.com/prometheus/client_golang"
@@ -60,4 +60,4 @@

[[constraint]]
  name = "github.com/stretchr/testify"
  version = "~1.1.4"
  version = "~1.2.1"

ga/ga.go

0 → 100644
+117 −0
Original line number Diff line number Diff line
// Copyright 2018 The Nakama Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ga

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"regexp"
)

const gaURL = "https://www.google-analytics.com/collect"

var gacodeRegexp = regexp.MustCompile(`^UA-\d+-\d+$`)

// Event is a GA event.
type Event struct {
	Ec string // event category
	Ea string // event action
	El string // event label
	Ev string // event value
}

// AppInfo represents a mobile app info GA event.
type AppInfo struct {
	An   string // app name
	Aid  string // app identifier
	Av   string // app version
	Aiid string // app installer identifier
}

// SendAppInfo will send the AppInfo struct to GA over HTTP.
func SendAppInfo(httpc *http.Client, gacode string, cookie string, app *AppInfo) error {
	values := url.Values{}
	values.Add("an", app.An)
	values.Add("av", app.Av)
	values.Add("aid", app.Aid)
	values.Add("aiid", app.Aiid)
	return SendValues(httpc, gacode, cookie, values)
}

// SendEvent will send the event struct to GA over HTTP.
func SendEvent(httpc *http.Client, gacode string, cookie string, event *Event) error {
	if len(event.Ec) < 1 || len(event.Ea) < 1 {
		return errors.New("event category/action must be set")
	}

	values := url.Values{}
	values.Add("ec", event.Ec)
	values.Add("ea", event.Ea)

	if len(event.El) > 0 {
		values.Add("el", event.El)
	}
	if len(event.Ev) > 0 {
		values.Add("ev", event.Ev)
	}

	values.Add("t", "event")
	return SendValues(httpc, gacode, cookie, values)
}

// SendValues will send supplied values to GA over HTTP.
func SendValues(httpc *http.Client, gacode string, cookie string, values url.Values) error {
	if !gacodeRegexp.MatchString(gacode) {
		return errors.New("invalid tracking id")
	}

	// Add required params
	values.Add("v", "1")
	values.Add("tid", gacode)
	values.Add("cid", cookie)

	// Send request
	buf := bytes.NewBufferString(values.Encode())
	resp, err := httpc.Post(gaURL, "application/x-www-form-urlencoded", buf)
	if err != nil {
		return err
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		return fmt.Errorf("request failed with '%v' status", resp.StatusCode)
	}
	return nil
}

// SendSessionStart will send a session start event to GA over HTTP.
func SendSessionStart(httpc *http.Client, gacode string, cookie string) error {
	values := url.Values{}
	values.Add("t", "event")
	values.Add("sc", "start")
	return SendValues(httpc, gacode, cookie, values)
}

// SendSessionStop will send a session stop event to GA over HTTP.
func SendSessionStop(httpc *http.Client, gacode string, cookie string) error {
	values := url.Values{}
	values.Add("t", "event")
	values.Add("sc", "end")
	return SendValues(httpc, gacode, cookie, values)
}
+60 −3
Original line number Diff line number Diff line
@@ -28,13 +28,19 @@ import (
	"time"

	"github.com/golang/protobuf/jsonpb"
	"github.com/heroiclabs/nakama/ga"
	"github.com/heroiclabs/nakama/migrate"
	"github.com/heroiclabs/nakama/server"
	"github.com/heroiclabs/nakama/social"
	_ "github.com/lib/pq"
	"github.com/satori/go.uuid"
	"go.uber.org/zap"
	"io/ioutil"
	"path/filepath"
)

const cookieFilename = ".cookie"

var (
	version  string = "2.0.0"
	commitID string = "dev"
@@ -111,6 +117,13 @@ func main() {
	metrics := server.NewMetrics(multiLogger, config)
	apiServer := server.StartApiServer(jsonLogger, multiLogger, db, jsonpbMarshaler, jsonpbUnmarshaler, config, socialClient, sessionRegistry, matchRegistry, tracker, router, pipeline, runtimePool)

	gaenabled := len(os.Getenv("NAKAMA_TELEMETRY")) < 1
	cookie := newOrLoadCookie(config)
	gacode := "UA-89792135-1"
	if gaenabled {
		runTelemetry(jsonLogger, http.DefaultClient, gacode, cookie)
	}

	// Respect OS stop signals.
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
@@ -128,6 +141,10 @@ func main() {
	tracker.Stop()
	sessionRegistry.Stop()

	if gaenabled {
		ga.SendSessionStop(http.DefaultClient, gacode, cookie)
	}

	os.Exit(0)
}

@@ -155,9 +172,6 @@ func dbConnect(multiLogger *zap.Logger, config server.Config) (*sql.DB, string)
	if err != nil {
		multiLogger.Fatal("Error pinging database", zap.Error(err))
	}
	db.SetConnMaxLifetime(time.Millisecond * time.Duration(config.GetDatabase().ConnMaxLifetimeMs))
	db.SetMaxOpenConns(config.GetDatabase().MaxOpenConns)
	db.SetMaxIdleConns(config.GetDatabase().MaxIdleConns)

	db.SetConnMaxLifetime(time.Millisecond * time.Duration(config.GetDatabase().ConnMaxLifetimeMs))
	db.SetMaxOpenConns(config.GetDatabase().MaxOpenConns)
@@ -170,3 +184,46 @@ func dbConnect(multiLogger *zap.Logger, config server.Config) (*sql.DB, string)

	return db, dbVersion
}

// Help improve Nakama by sending anonymous usage statistics.
//
// You can disable the telemetry completely before server start by setting the
// environment variable "NAKAMA_TELEMETRY" - i.e. NAKAMA_TELEMETRY=0 nakama
//
// These properties are collected:
// * A unique UUID v4 random identifier which is generated.
// * Version of Nakama being used which includes build metadata.
// * Amount of time the server ran for.
//
// This information is sent via Google Analytics which allows the Nakama team to
// analyze usage patterns and errors in order to help improve the server.
func runTelemetry(logger *zap.Logger, httpc *http.Client, gacode string, cookie string) {
	err := ga.SendSessionStart(httpc, gacode, cookie)
	if err != nil {
		logger.Debug("Send start session event failed.", zap.Error(err))
		return
	}

	err = ga.SendEvent(httpc, gacode, cookie, &ga.Event{Ec: "version", Ea: fmt.Sprintf("%s+%s", version, commitID)})
	if err != nil {
		logger.Debug("Send event failed.", zap.Error(err))
		return
	}

	err = ga.SendEvent(httpc, gacode, cookie, &ga.Event{Ec: "variant", Ea: "nakama"})
	if err != nil {
		logger.Debug("Send event failed.", zap.Error(err))
		return
	}
}

func newOrLoadCookie(config server.Config) string {
	filePath := filepath.FromSlash(config.GetDataDir() + "/" + cookieFilename)
	b, err := ioutil.ReadFile(filePath)
	cookie := uuid.FromBytesOrNil(b)
	if err != nil || cookie == uuid.Nil {
		cookie = uuid.Must(uuid.NewV4())
		ioutil.WriteFile(filePath, cookie.Bytes(), 0644)
	}
	return cookie.String()
}
+1 −1
Original line number Diff line number Diff line
@@ -9,5 +9,5 @@ import "github.com/gobuffalo/packr"
// Go binary. You can use the "packr clean" command to clean up this,
// and any other packr generated files.
func init() {
	packr.PackJSONBytes("./sql", "20180103142001_initial_schema.sql", "\"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\"")
	packr.PackJSONBytes("./sql", "20180103142001_initial_schema.sql", "\"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\"")
}
Loading