Skip to content

Commit

Permalink
add debug api
Browse files Browse the repository at this point in the history
  • Loading branch information
SealTV committed Aug 8, 2023
1 parent 7035afc commit cc01150
Show file tree
Hide file tree
Showing 8 changed files with 418 additions and 177 deletions.
11 changes: 11 additions & 0 deletions src/internal/api/gateway/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type API struct {
Request *RequestHandler
User *UserHandler
Contribution *ContributionHandler
Debug *DebugHandler
}

func New(cfg *config.Config, infra *infrastructure.Infra) *API {
Expand Down Expand Up @@ -89,6 +90,7 @@ func New(cfg *config.Config, infra *infrastructure.Infra) *API {
User: NewUserHandler(userSvc),
Contribution: NewContributionHandler(contribution, userSvc, templateService, compositionService, cfg.BaseURL),
Directory: NewDirectoryHandler(directory, userSvc, docService.Infra.Index, cfg.BaseURL),
Debug: NewDebugHandler(docService.Proc, docService.Infra.Index),
}
}

Expand All @@ -103,6 +105,7 @@ func (a *API) Build() *gin.Engine {
a.buildQueryAPI(),
a.buildDefinitionAPI(),
a.buildRequestsAPI(),
a.buildDebugAPI(),
)
}

Expand Down Expand Up @@ -150,6 +153,7 @@ func (a *API) setupRouter(apiHandlers ...handlerBuilder) *gin.Engine {
}))

r.Use(requestID)
// r.Use(middleware)

v1 := r.Group("v1")
for _, b := range apiHandlers {
Expand All @@ -162,6 +166,13 @@ func (a *API) setupRouter(apiHandlers ...handlerBuilder) *gin.Engine {
return r
}

func (a *API) buildDebugAPI() handlerBuilder {
return func(r *gin.RouterGroup) {
r = r.Group("debug")
r.GET("/eth_transactions", a.Debug.GetEthTransactions)
}
}

func (a *API) buildEhrAPI() handlerBuilder {
return func(r *gin.RouterGroup) {
r = r.Group("ehr")
Expand Down
177 changes: 177 additions & 0 deletions src/internal/api/gateway/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package gateway

import (
"context"
"encoding/csv"
"fmt"
"net/http"
"sync"
"time"

"github.com/bsn-si/IPEHR-gateway/src/pkg/docs/service/processing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/gin-gonic/gin"
)

type Storage interface {
GetAllRequests(ctx context.Context) ([]*processing.Request, error)
GetEthTransactionsForRequest(ctx context.Context, reqID string) ([]*processing.EthereumTx, error)
GetAllEthTransactions(ctx context.Context) ([]*processing.EthereumTx, error)
}

type EthIndexer interface {
GetTxReceipt(ctx context.Context, hash string) (*types.Receipt, error)
}

type DebugHandler struct {
storage Storage
indexer EthIndexer
}

func NewDebugHandler(storage Storage, indexer EthIndexer) *DebugHandler {
return &DebugHandler{
storage: storage,
indexer: indexer,
}
}

func (d *DebugHandler) GetEthTransactions(c *gin.Context) {
requests, err := d.storage.GetAllRequests(c.Request.Context())
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)

Check failure on line 41 in src/internal/api/gateway/debug.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `c.AbortWithError` is not checked (errcheck)
return
}

result := [][]string{
{
"req_id",
"time_start",
"time_end",
"duration",
"full_path",
"req_kind",
"req_status",
"tx_kind",
"tx_status",
"tx_cumulativeGasUsed",
"gas",
"block_number",
"transaction_index",
},
}

rrs := []req{}

mx.RLock()
for _, rr := range rMap {
rrs = append(rrs, rr)
}
mx.RUnlock()

for _, rr := range rrs {
var req *processing.Request

for _, r := range requests {
if r.ReqID == rr.reqID || r.ReqID == rr.reqID+"_register" {
req = r
break
}
}

if req == nil {
result = append(result, []string{
rr.reqID,
rr.start.Format("2006-01-02 15:04:05"),
rr.end.Format("2006-01-02 15:04:05"),
fmt.Sprintf("%v", rr.end.Sub(rr.start).Seconds()),
rr.url,
"",
"",
"",
"",
"",
"",
"",
"",
})

continue
}

txs, err := d.storage.GetEthTransactionsForRequest(c.Request.Context(), req.ReqID)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)

Check failure on line 103 in src/internal/api/gateway/debug.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `c.AbortWithError` is not checked (errcheck)
return
}

for _, tx := range txs {
r, err := d.indexer.GetTxReceipt(c.Request.Context(), tx.Hash)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)

Check failure on line 110 in src/internal/api/gateway/debug.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `c.AbortWithError` is not checked (errcheck)
return
}

result = append(result, []string{
rr.reqID,
rr.start.Format("2006-01-02 15:04:05"),
rr.end.Format("2006-01-02 15:04:05"),
fmt.Sprintf("%v", rr.end.Sub(rr.start).Seconds()),
rr.url,
req.Kind.String(),
req.Status.String(),
tx.Kind.String(),
fmt.Sprintf("%d", r.Status),
fmt.Sprintf("%d", r.CumulativeGasUsed),
fmt.Sprintf("%d", r.GasUsed),
r.BlockNumber.Text(10),
fmt.Sprintf("%d", r.TransactionIndex),
})
}
}

// convert result to csv and send it
csvWriter := csv.NewWriter(c.Writer)
if err := csvWriter.WriteAll(result); err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}

csvWriter.Flush()

if err := csvWriter.Error(); err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.Status(http.StatusOK)
}

type req struct {
reqID string
url string
start time.Time
end time.Time
}

var (
rMap = map[string]req{}

mx = sync.RWMutex{}
)

func middleware(c *gin.Context) {

Check failure on line 162 in src/internal/api/gateway/debug.go

View workflow job for this annotation

GitHub Actions / lint

func `middleware` is unused (unused)
r := req{
reqID: c.GetString("reqID"),
start: time.Now(),
url: c.FullPath(),
}

// serve the request to the next middleware
c.Next()

r.end = time.Now()

mx.Lock()
rMap[r.reqID] = r
mx.Unlock()
}
Loading

0 comments on commit cc01150

Please sign in to comment.