mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: add metric plugin (#361)
This commit is contained in:
@ -8,6 +8,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
"github.com/usememos/memos/server"
|
"github.com/usememos/memos/server"
|
||||||
"github.com/usememos/memos/server/profile"
|
"github.com/usememos/memos/server/profile"
|
||||||
"github.com/usememos/memos/store"
|
"github.com/usememos/memos/store"
|
||||||
@ -34,15 +35,20 @@ func run(profile *profile.Profile) error {
|
|||||||
return fmt.Errorf("cannot open db: %w", err)
|
return fmt.Errorf("cannot open db: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := server.NewServer(profile)
|
serverInstance := server.NewServer(profile)
|
||||||
|
|
||||||
storeInstance := store.New(db.Db, profile)
|
storeInstance := store.New(db.Db, profile)
|
||||||
s.Store = storeInstance
|
serverInstance.Store = storeInstance
|
||||||
|
|
||||||
|
metricCollector := server.NewMetricCollector(profile, storeInstance)
|
||||||
|
serverInstance.Collector = &metricCollector
|
||||||
|
|
||||||
println(greetingBanner)
|
println(greetingBanner)
|
||||||
fmt.Printf("Version %s has started at :%d\n", profile.Version, profile.Port)
|
fmt.Printf("Version %s has started at :%d\n", profile.Version, profile.Port)
|
||||||
|
metricCollector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "servive started",
|
||||||
|
})
|
||||||
|
|
||||||
return s.Run()
|
return serverInstance.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func execute() error {
|
func execute() error {
|
||||||
|
9
go.mod
9
go.mod
@ -33,8 +33,15 @@ require (
|
|||||||
github.com/labstack/echo-contrib v0.13.0
|
github.com/labstack/echo-contrib v0.13.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||||
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
|
github.com/segmentio/backo-go v1.0.1 // indirect
|
||||||
|
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/segmentio/analytics-go v3.1.0+incompatible
|
||||||
)
|
)
|
||||||
|
8
go.sum
8
go.sum
@ -52,6 +52,8 @@ github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhpl
|
|||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/casbin/casbin/v2 v2.51.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
github.com/casbin/casbin/v2 v2.51.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
@ -277,6 +279,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
|||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/segmentio/analytics-go v3.1.0+incompatible h1:IyiOfUgQFVHvsykKKbdI7ZsH374uv3/DfZUo9+G0Z80=
|
||||||
|
github.com/segmentio/analytics-go v3.1.0+incompatible/go.mod h1:C7CYBtQWk4vRk2RyLu0qOcbHJ18E3F1HV2C/8JvKN48=
|
||||||
|
github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N++y4=
|
||||||
|
github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
@ -301,6 +307,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
|
|||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||||
|
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
|
||||||
|
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
6
plugin/metrics/collector.go
Normal file
6
plugin/metrics/collector.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package metric
|
||||||
|
|
||||||
|
// Collector is the interface definition for metric collector.
|
||||||
|
type Collector interface {
|
||||||
|
Collect(metric *Metric) error
|
||||||
|
}
|
7
plugin/metrics/metric.go
Normal file
7
plugin/metrics/metric.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package metric
|
||||||
|
|
||||||
|
// Metric is the API message for metric.
|
||||||
|
type Metric struct {
|
||||||
|
Name string
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
40
plugin/metrics/segment/collector.go
Normal file
40
plugin/metrics/segment/collector.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package segment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/segmentio/analytics-go"
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ metric.Collector = (*collector)(nil)
|
||||||
|
|
||||||
|
// collector is the metrics collector https://segment.com/.
|
||||||
|
type collector struct {
|
||||||
|
client analytics.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCollector creates a new instance of segment.
|
||||||
|
func NewCollector(key string) metric.Collector {
|
||||||
|
client := analytics.New(key)
|
||||||
|
|
||||||
|
return &collector{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect will exec all the segment collector.
|
||||||
|
func (c *collector) Collect(metric *metric.Metric) error {
|
||||||
|
properties := analytics.NewProperties()
|
||||||
|
for key, value := range metric.Labels {
|
||||||
|
properties.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.client.Enqueue(analytics.Track{
|
||||||
|
Event: string(metric.Name),
|
||||||
|
AnonymousId: uuid.NewString(),
|
||||||
|
Properties: properties,
|
||||||
|
Timestamp: time.Now().UTC(),
|
||||||
|
})
|
||||||
|
}
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"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"
|
||||||
@ -42,6 +43,9 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
if err = setUserSession(c, user); err != nil {
|
if err = setUserSession(c, user); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to set signin session").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to set signin session").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "user signed in",
|
||||||
|
})
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil {
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil {
|
||||||
@ -51,10 +55,14 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
g.POST("/auth/logout", func(c echo.Context) error {
|
g.POST("/auth/logout", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
err := removeUserSession(c)
|
err := removeUserSession(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to set logout session").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to set logout session").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "user logout",
|
||||||
|
})
|
||||||
|
|
||||||
c.Response().WriteHeader(http.StatusOK)
|
c.Response().WriteHeader(http.StatusOK)
|
||||||
return nil
|
return nil
|
||||||
@ -102,6 +110,9 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "user signed up",
|
||||||
|
})
|
||||||
|
|
||||||
err = setUserSession(c, user)
|
err = setUserSession(c, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@ -60,6 +61,9 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create memo").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "memo created",
|
||||||
|
})
|
||||||
|
|
||||||
for _, resourceID := range memoCreate.ResourceIDList {
|
for _, resourceID := range memoCreate.ResourceIDList {
|
||||||
if _, err := s.Store.UpsertMemoResource(ctx, &api.MemoResourceUpsert{
|
if _, err := s.Store.UpsertMemoResource(ctx, &api.MemoResourceUpsert{
|
||||||
|
49
server/metric_collector.go
Normal file
49
server/metric_collector.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
metric "github.com/usememos/memos/plugin/metrics"
|
||||||
|
"github.com/usememos/memos/plugin/metrics/segment"
|
||||||
|
"github.com/usememos/memos/server/profile"
|
||||||
|
"github.com/usememos/memos/server/version"
|
||||||
|
"github.com/usememos/memos/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MetricCollector is the metric collector.
|
||||||
|
type MetricCollector struct {
|
||||||
|
collector metric.Collector
|
||||||
|
profile *profile.Profile
|
||||||
|
store *store.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
segmentMetricWriteKey = "FqYUl1CmssHytFSnnVd0efV4gyGeH0dx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewMetricCollector(profile *profile.Profile, store *store.Store) MetricCollector {
|
||||||
|
c := segment.NewCollector(segmentMetricWriteKey)
|
||||||
|
|
||||||
|
return MetricCollector{
|
||||||
|
collector: c,
|
||||||
|
profile: profile,
|
||||||
|
store: store,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MetricCollector) Collect(_ context.Context, metric *metric.Metric) {
|
||||||
|
if mc.profile.Mode == "dev" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if metric.Labels == nil {
|
||||||
|
metric.Labels = map[string]string{}
|
||||||
|
}
|
||||||
|
metric.Labels["version"] = version.GetCurrentVersion(mc.profile.Mode)
|
||||||
|
|
||||||
|
err := mc.collector.Collect(metric)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to request segment, error: %+v\n", err)
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@ -58,6 +59,9 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "resource created",
|
||||||
|
})
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil {
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil {
|
||||||
|
@ -17,6 +17,8 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
e *echo.Echo
|
e *echo.Echo
|
||||||
|
|
||||||
|
Collector *MetricCollector
|
||||||
|
|
||||||
Profile *profile.Profile
|
Profile *profile.Profile
|
||||||
|
|
||||||
Store *store.Store
|
Store *store.Store
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@ -31,6 +32,9 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create shortcut").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create shortcut").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "shortcut created",
|
||||||
|
})
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(shortcut)); err != nil {
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(shortcut)); err != nil {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"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"
|
||||||
@ -52,6 +53,9 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
s.Collector.Collect(ctx, &metric.Metric{
|
||||||
|
Name: "user created",
|
||||||
|
})
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil {
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil {
|
||||||
|
Reference in New Issue
Block a user