Skip to content

Commit

Permalink
Merge pull request #129 from anyproto/go-3582-filenode-space-size-met…
Browse files Browse the repository at this point in the history
…hod-to-debug-server-analytics

GO-3582: filenode space size method to debug server analytics
  • Loading branch information
cheggaaa authored Aug 19, 2024
2 parents f54290e + 3e1723a commit 9856a33
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 6 deletions.
2 changes: 2 additions & 0 deletions cmd/filenode.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/anyproto/any-sync-filenode/filenode"
"github.com/anyproto/any-sync-filenode/index"
"github.com/anyproto/any-sync-filenode/redisprovider"
"github.com/anyproto/any-sync-filenode/stat"

// import this to keep govvv in go.mod on mod tidy
_ "github.com/ahmetb/govvv/integration-test/app-different-package/mypkg"
Expand Down Expand Up @@ -106,6 +107,7 @@ func main() {

func Bootstrap(a *app.App) {
a.Register(account.New()).
Register(stat.New()).
Register(metric.New()).
Register(nodeconfsource.New()).
Register(nodeconfstore.New()).
Expand Down
27 changes: 22 additions & 5 deletions filenode/filenode.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,34 @@ func (fn *fileNode) SpaceInfo(ctx context.Context, spaceId string) (info *filepr
return
}

func (fn *fileNode) AccountInfo(ctx context.Context) (info *fileproto.AccountInfoResponse, err error) {
info = &fileproto.AccountInfoResponse{}
func (fn *fileNode) BatchAccountInfo(ctx context.Context, identities []string) ([]*fileproto.AccountInfoResponse, error) {
accountInfos := make([]*fileproto.AccountInfoResponse, 0, len(identities))
for _, identity := range identities {
accountInfo, err := fn.accountInfo(ctx, identity)
if err != nil {
return nil, err
}
accountInfos = append(accountInfos, accountInfo)
}
return accountInfos, nil
}

func (fn *fileNode) AccountInfo(ctx context.Context, identity string) (*fileproto.AccountInfoResponse, error) {
return fn.accountInfo(ctx, identity)
}

func (fn *fileNode) AccountInfoCtx(ctx context.Context) (info *fileproto.AccountInfoResponse, err error) {
identity, err := peer.CtxPubKey(ctx)
if err != nil {
return nil, fileprotoerr.ErrForbidden
}

groupId := identity.Account()
return fn.accountInfo(ctx, groupId)
}

groupInfo, err := fn.index.GroupInfo(ctx, groupId)
func (fn *fileNode) accountInfo(ctx context.Context, identity string) (info *fileproto.AccountInfoResponse, err error) {
info = &fileproto.AccountInfoResponse{}
groupInfo, err := fn.index.GroupInfo(ctx, identity)
if err != nil {
return nil, err
}
Expand All @@ -250,7 +267,7 @@ func (fn *fileNode) AccountInfo(ctx context.Context) (info *fileproto.AccountInf
info.LimitBytes = groupInfo.Limit
info.AccountLimitBytes = groupInfo.AccountLimit
for _, spaceId := range groupInfo.SpaceIds {
spaceInfo, err := fn.spaceInfo(ctx, index.Key{GroupId: groupId, SpaceId: spaceId}, groupInfo)
spaceInfo, err := fn.spaceInfo(ctx, index.Key{GroupId: identity, SpaceId: spaceId}, groupInfo)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion filenode/rpchandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func (r rpcHandler) AccountInfo(ctx context.Context, req *fileproto.AccountInfoR
zap.Error(err),
)
}()
if resp, err = r.f.AccountInfo(ctx); err != nil {
if resp, err = r.f.AccountInfoCtx(ctx); err != nil {
return
}
return
Expand Down
86 changes: 86 additions & 0 deletions stat/identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package stat

import (
"context"
"encoding/json"
"net/http"

"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonfile/fileproto"
)

const CName = "stat.identity"

type accountInfoProvider interface {
AccountInfo(ctx context.Context, identity string) (*fileproto.AccountInfoResponse, error)
BatchAccountInfo(ctx context.Context, identities []string) ([]*fileproto.AccountInfoResponse, error)
}

type Stat interface {
app.ComponentRunnable
}

func New() Stat {
return &identityStat{}
}

type identityStat struct {
accountInfoProvider accountInfoProvider
}

func (i *identityStat) Init(a *app.App) (err error) {
i.accountInfoProvider = app.MustComponent[accountInfoProvider](a)
return
}

func (i *identityStat) Name() (name string) {
return CName
}

func (i *identityStat) Run(ctx context.Context) (err error) {
http.HandleFunc("/stat/identity/{identity}", func(writer http.ResponseWriter, request *http.Request) {
identity := request.PathValue("identity")
if identity == "" {
http.Error(writer, "identity is empty", http.StatusBadRequest)
return
}
accountInfo, err := i.accountInfoProvider.AccountInfo(request.Context(), identity)
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)
err = json.NewEncoder(writer).Encode(accountInfo)
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
})
http.HandleFunc("/stat/identities", func(writer http.ResponseWriter, request *http.Request) {
data := struct {
Ids []string `json:"ids"`
}{}
if err := json.NewDecoder(request.Body).Decode(&data); err != nil {
http.Error(writer, "invalid JSON", http.StatusBadRequest)
return
}
accountInfos, err := i.accountInfoProvider.BatchAccountInfo(request.Context(), data.Ids)
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)
err = json.NewEncoder(writer).Encode(accountInfos)
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
})
return nil
}

func (i *identityStat) Close(ctx context.Context) (err error) {
return
}

0 comments on commit 9856a33

Please sign in to comment.