mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update activity metrics (#908)
This commit is contained in:
@ -1,6 +1,14 @@
|
|||||||
package metric
|
package metric
|
||||||
|
|
||||||
|
// Metric is the API message for metric.
|
||||||
|
type Metric struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
// Collector is the interface definition for metric collector.
|
// Collector is the interface definition for metric collector.
|
||||||
type Collector interface {
|
type Collector interface {
|
||||||
|
Identify(id string) error
|
||||||
Collect(metric *Metric) error
|
Collect(metric *Metric) error
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package metric
|
|
||||||
|
|
||||||
// Metric is the API message for metric.
|
|
||||||
type Metric struct {
|
|
||||||
Name string
|
|
||||||
Labels map[string]string
|
|
||||||
}
|
|
@ -3,15 +3,10 @@ package segment
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/segmentio/analytics-go"
|
"github.com/segmentio/analytics-go"
|
||||||
metric "github.com/usememos/memos/plugin/metrics"
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
sessionUUID = uuid.NewString()
|
|
||||||
)
|
|
||||||
|
|
||||||
// collector is the metrics collector https://segment.com/.
|
// collector is the metrics collector https://segment.com/.
|
||||||
type collector struct {
|
type collector struct {
|
||||||
client analytics.Client
|
client analytics.Client
|
||||||
@ -26,6 +21,14 @@ func NewCollector(key string) metric.Collector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Identify will identify the server caller.
|
||||||
|
func (c *collector) Identify(id string) error {
|
||||||
|
return c.client.Enqueue(analytics.Identify{
|
||||||
|
UserId: id,
|
||||||
|
Timestamp: time.Now().UTC(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Collect will exec all the segment collector.
|
// Collect will exec all the segment collector.
|
||||||
func (c *collector) Collect(metric *metric.Metric) error {
|
func (c *collector) Collect(metric *metric.Metric) error {
|
||||||
properties := analytics.NewProperties()
|
properties := analytics.NewProperties()
|
||||||
@ -34,9 +37,9 @@ func (c *collector) Collect(metric *metric.Metric) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.client.Enqueue(analytics.Track{
|
return c.client.Enqueue(analytics.Track{
|
||||||
Event: string(metric.Name),
|
UserId: metric.ID,
|
||||||
AnonymousId: sessionUUID,
|
Timestamp: time.Now().UTC(),
|
||||||
Properties: properties,
|
Event: metric.Name,
|
||||||
Timestamp: time.Now().UTC(),
|
Properties: properties,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/usememos/memos/api"
|
"github.com/usememos/memos/api"
|
||||||
"github.com/usememos/memos/common"
|
"github.com/usememos/memos/common"
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@ -150,12 +151,15 @@ func (s *Server) createUserAuthSignInActivity(c echo.Context, user *api.User) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshal activity payload")
|
return errors.Wrap(err, "failed to marshal activity payload")
|
||||||
}
|
}
|
||||||
_, err = s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
||||||
CreatorID: user.ID,
|
CreatorID: user.ID,
|
||||||
Type: api.ActivityUserAuthSignIn,
|
Type: api.ActivityUserAuthSignIn,
|
||||||
Level: api.ActivityInfo,
|
Level: api.ActivityInfo,
|
||||||
Payload: string(payloadStr),
|
Payload: string(payloadStr),
|
||||||
})
|
})
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: string(activity.Type),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,11 +173,14 @@ func (s *Server) createUserAuthSignUpActivity(c echo.Context, user *api.User) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshal activity payload")
|
return errors.Wrap(err, "failed to marshal activity payload")
|
||||||
}
|
}
|
||||||
_, err = s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
||||||
CreatorID: user.ID,
|
CreatorID: user.ID,
|
||||||
Type: api.ActivityUserAuthSignUp,
|
Type: api.ActivityUserAuthSignUp,
|
||||||
Level: api.ActivityInfo,
|
Level: api.ActivityInfo,
|
||||||
Payload: string(payloadStr),
|
Payload: string(payloadStr),
|
||||||
})
|
})
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: string(activity.Type),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/usememos/memos/api"
|
"github.com/usememos/memos/api"
|
||||||
"github.com/usememos/memos/common"
|
"github.com/usememos/memos/common"
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -576,11 +577,14 @@ func (s *Server) createMemoCreateActivity(c echo.Context, memo *api.Memo) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshal activity payload")
|
return errors.Wrap(err, "failed to marshal activity payload")
|
||||||
}
|
}
|
||||||
_, err = s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
||||||
CreatorID: memo.CreatorID,
|
CreatorID: memo.CreatorID,
|
||||||
Type: api.ActivityMemoCreate,
|
Type: api.ActivityMemoCreate,
|
||||||
Level: api.ActivityInfo,
|
Level: api.ActivityInfo,
|
||||||
Payload: string(payloadStr),
|
Payload: string(payloadStr),
|
||||||
})
|
})
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: string(activity.Type),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -8,29 +8,39 @@ import (
|
|||||||
"github.com/usememos/memos/plugin/metrics/segment"
|
"github.com/usememos/memos/plugin/metrics/segment"
|
||||||
"github.com/usememos/memos/server/profile"
|
"github.com/usememos/memos/server/profile"
|
||||||
"github.com/usememos/memos/server/version"
|
"github.com/usememos/memos/server/version"
|
||||||
"github.com/usememos/memos/store"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MetricCollector is the metric collector.
|
// MetricCollector is the metric collector.
|
||||||
type MetricCollector struct {
|
type MetricCollector struct {
|
||||||
Collector metric.Collector
|
collector metric.Collector
|
||||||
|
ID string
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Profile *profile.Profile
|
Profile *profile.Profile
|
||||||
Store *store.Store
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
segmentMetricWriteKey = "fTn5BumOkj352n3TGw9tu0ARH2dOkcoQ"
|
segmentMetricWriteKey = "NbPruMMmfqfD2AMCw3pkxZTsszVS3hKq"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewMetricCollector(profile *profile.Profile, store *store.Store) MetricCollector {
|
func (s *Server) registerMetricCollector() {
|
||||||
c := segment.NewCollector(segmentMetricWriteKey)
|
c := segment.NewCollector(segmentMetricWriteKey)
|
||||||
|
mc := &MetricCollector{
|
||||||
return MetricCollector{
|
collector: c,
|
||||||
Collector: c,
|
ID: s.ID,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Profile: profile,
|
Profile: s.Profile,
|
||||||
Store: store,
|
}
|
||||||
|
s.Collector = mc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MetricCollector) Identify(_ context.Context) {
|
||||||
|
if !mc.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mc.collector.Identify(mc.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to request segment, error: %+v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,16 +49,13 @@ func (mc *MetricCollector) Collect(_ context.Context, metric *metric.Metric) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if mc.Profile.Mode == "dev" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if metric.Labels == nil {
|
if metric.Labels == nil {
|
||||||
metric.Labels = map[string]string{}
|
metric.Labels = map[string]string{}
|
||||||
}
|
}
|
||||||
|
metric.Labels["mode"] = mc.Profile.Mode
|
||||||
metric.Labels["version"] = version.GetCurrentVersion(mc.Profile.Mode)
|
metric.Labels["version"] = version.GetCurrentVersion(mc.Profile.Mode)
|
||||||
|
metric.ID = mc.ID
|
||||||
err := mc.Collector.Collect(metric)
|
err := mc.collector.Collect(metric)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to request segment, error: %+v\n", err)
|
fmt.Printf("Failed to request segment, error: %+v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/usememos/memos/api"
|
"github.com/usememos/memos/api"
|
||||||
"github.com/usememos/memos/common"
|
"github.com/usememos/memos/common"
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -287,11 +288,14 @@ func (s *Server) createResourceCreateActivity(c echo.Context, resource *api.Reso
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshal activity payload")
|
return errors.Wrap(err, "failed to marshal activity payload")
|
||||||
}
|
}
|
||||||
_, err = s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
||||||
CreatorID: resource.CreatorID,
|
CreatorID: resource.CreatorID,
|
||||||
Type: api.ActivityResourceCreate,
|
Type: api.ActivityResourceCreate,
|
||||||
Level: api.ActivityInfo,
|
Level: api.ActivityInfo,
|
||||||
Payload: string(payloadStr),
|
Payload: string(payloadStr),
|
||||||
})
|
})
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: string(activity.Type),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/usememos/memos/api"
|
"github.com/usememos/memos/api"
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
"github.com/usememos/memos/server/profile"
|
"github.com/usememos/memos/server/profile"
|
||||||
"github.com/usememos/memos/store"
|
"github.com/usememos/memos/store"
|
||||||
"github.com/usememos/memos/store/db"
|
"github.com/usememos/memos/store/db"
|
||||||
@ -46,11 +47,6 @@ func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) {
|
|||||||
storeInstance := store.New(db.DBInstance, profile)
|
storeInstance := store.New(db.DBInstance, profile)
|
||||||
s.Store = storeInstance
|
s.Store = storeInstance
|
||||||
|
|
||||||
metricCollector := NewMetricCollector(profile, storeInstance)
|
|
||||||
// Disable metrics collector.
|
|
||||||
metricCollector.Enabled = false
|
|
||||||
s.Collector = &metricCollector
|
|
||||||
|
|
||||||
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||||
Format: `{"time":"${time_rfc3339}",` +
|
Format: `{"time":"${time_rfc3339}",` +
|
||||||
`"method":"${method}","uri":"${uri}",` +
|
`"method":"${method}","uri":"${uri}",` +
|
||||||
@ -93,6 +89,9 @@ func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) {
|
|||||||
|
|
||||||
embedFrontend(e)
|
embedFrontend(e)
|
||||||
|
|
||||||
|
// Register MetricCollector to server.
|
||||||
|
s.registerMetricCollector()
|
||||||
|
|
||||||
rootGroup := e.Group("")
|
rootGroup := e.Group("")
|
||||||
s.registerRSSRoutes(rootGroup)
|
s.registerRSSRoutes(rootGroup)
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ func (s *Server) Run(ctx context.Context) error {
|
|||||||
if err := s.createServerStartActivity(ctx); err != nil {
|
if err := s.createServerStartActivity(ctx); err != nil {
|
||||||
return errors.Wrap(err, "failed to create activity")
|
return errors.Wrap(err, "failed to create activity")
|
||||||
}
|
}
|
||||||
|
s.Collector.Identify(ctx)
|
||||||
return s.e.Start(fmt.Sprintf(":%d", s.Profile.Port))
|
return s.e.Start(fmt.Sprintf(":%d", s.Profile.Port))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +134,14 @@ func (s *Server) createServerStartActivity(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshal activity payload")
|
return errors.Wrap(err, "failed to marshal activity payload")
|
||||||
}
|
}
|
||||||
_, err = s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
||||||
CreatorID: api.UnknownID,
|
CreatorID: api.UnknownID,
|
||||||
Type: api.ActivityServerStart,
|
Type: api.ActivityServerStart,
|
||||||
Level: api.ActivityInfo,
|
Level: api.ActivityInfo,
|
||||||
Payload: string(payloadStr),
|
Payload: string(payloadStr),
|
||||||
})
|
})
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: string(activity.Type),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/usememos/memos/api"
|
"github.com/usememos/memos/api"
|
||||||
"github.com/usememos/memos/common"
|
"github.com/usememos/memos/common"
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@ -289,11 +290,14 @@ func (s *Server) createUserCreateActivity(c echo.Context, user *api.User) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshal activity payload")
|
return errors.Wrap(err, "failed to marshal activity payload")
|
||||||
}
|
}
|
||||||
_, err = s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
|
||||||
CreatorID: user.ID,
|
CreatorID: user.ID,
|
||||||
Type: api.ActivityUserCreate,
|
Type: api.ActivityUserCreate,
|
||||||
Level: api.ActivityInfo,
|
Level: api.ActivityInfo,
|
||||||
Payload: string(payloadStr),
|
Payload: string(payloadStr),
|
||||||
})
|
})
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: string(activity.Type),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,8 @@ func (s *Store) CreateActivity(ctx context.Context, create *api.ActivityCreate)
|
|||||||
return nil, FormatError(err)
|
return nil, FormatError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return activityRaw.toActivity(), nil
|
activity := activityRaw.toActivity()
|
||||||
|
return activity, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createActivity creates a new activity.
|
// createActivity creates a new activity.
|
||||||
|
Reference in New Issue
Block a user