-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Bingtan Lu <bingtlu@ebay.com>
- Loading branch information
Showing
14 changed files
with
723 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package probot | ||
|
||
import ( | ||
"context" | ||
"sort" | ||
"strings" | ||
"sync" | ||
|
||
"github.com/airconduct/go-probot/web/backend" | ||
) | ||
|
||
type eventMetrics struct { | ||
events sync.Map | ||
} | ||
|
||
var _ backend.EventSource = &eventMetrics{} | ||
|
||
func (m *eventMetrics) add(name, tp string) { | ||
m.events.Store(name, backend.Event{ | ||
Name: name, Type: backend.EventType(tp), | ||
Metrics: backend.EventMetrics{}, | ||
}) | ||
} | ||
|
||
func (m *eventMetrics) inc(name, tp string) { | ||
e, _ := m.events.LoadOrStore(name, backend.Event{ | ||
Name: name, Type: backend.EventType(tp), | ||
Metrics: backend.EventMetrics{}, | ||
}) | ||
event := e.(backend.Event) | ||
event.Metrics.Count++ | ||
m.events.Store(name, event) | ||
} | ||
|
||
func (m *eventMetrics) ListEvent(ctx context.Context, opts backend.ListOptions) (backend.EventList, error) { | ||
out := backend.EventList{} | ||
m.events.Range(func(key, value any) bool { | ||
out.Items = append(out.Items, value.(backend.Event)) | ||
return true | ||
}) | ||
sort.Slice(out.Items, func(i, j int) bool { | ||
return strings.Compare(out.Items[i].Name, out.Items[j].Name) < 0 | ||
}) | ||
if opts.Limit > 0 { | ||
start := opts.Offset * opts.Limit | ||
end := opts.Offset*opts.Limit + opts.Limit | ||
if start < 0 { | ||
start = 0 | ||
} else if start > int64(len(out.Items)) { | ||
start = int64(len(out.Items)) | ||
} | ||
if end < 0 { | ||
end = 0 | ||
} else if end > int64(len(out.Items)) { | ||
end = int64(len(out.Items)) | ||
} | ||
out.Items = out.Items[start:end] | ||
} | ||
return out, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package backend | ||
|
||
import ( | ||
"strconv" | ||
|
||
"github.com/emicklei/go-restful/v3" | ||
) | ||
|
||
func WithListOptionsParam(builder *restful.RouteBuilder) *restful.RouteBuilder { | ||
return builder.Param(restful.QueryParameter("page_size", "The maximum number of return items")). | ||
Param(restful.QueryParameter("page_num", "The first (page_size * page_num) items will be skipped.")). | ||
Param(restful.QueryParameter("filter", "The returned items will be filtered according to the filter.")) | ||
} | ||
|
||
func ListOptionsFromRequest(req *restful.Request) (opts ListOptions, err error) { | ||
if raw := req.QueryParameter("page_size"); raw != "" { | ||
opts.Limit, err = strconv.ParseInt(req.QueryParameter("page_size"), 10, 64) | ||
if err != nil { | ||
return | ||
} | ||
} | ||
if raw := req.QueryParameter("page_num"); raw != "" { | ||
opts.Offset, err = strconv.ParseInt(req.QueryParameter("page_num"), 10, 64) | ||
if err != nil { | ||
return | ||
} | ||
} | ||
opts.Filter = req.QueryParameter("filter") | ||
return | ||
} | ||
|
||
type ListOptions struct { | ||
Limit int64 | ||
Offset int64 | ||
Filter string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package backend | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
|
||
restfulspec "github.com/emicklei/go-restful-openapi/v2" | ||
"github.com/emicklei/go-restful/v3" | ||
) | ||
|
||
func AddEventService(ws *restful.WebService, es EventSource) { | ||
handler := &eventHandler{es: es} | ||
tags := []string{"events"} | ||
ws.Route(WithListOptionsParam( | ||
ws.GET("/events").To(handler.ListEvent). | ||
Metadata(restfulspec.KeyOpenAPITags, tags). | ||
Doc("get all events"). | ||
Returns(200, "OK", EventList{}), | ||
)) | ||
} | ||
|
||
type eventHandler struct { | ||
es EventSource | ||
} | ||
|
||
func (h *eventHandler) ListEvent(req *restful.Request, resp *restful.Response) { | ||
ctx, cancel := context.WithCancel(req.Request.Context()) | ||
defer cancel() | ||
opts, err := ListOptionsFromRequest(req) | ||
if err != nil { | ||
resp.WriteError(http.StatusBadRequest, err) | ||
return | ||
} | ||
|
||
events, err := h.es.ListEvent(ctx, opts) | ||
if err != nil { | ||
resp.WriteError(http.StatusBadRequest, err) | ||
return | ||
} | ||
if err := resp.WriteEntity(events); err != nil { | ||
resp.WriteError(http.StatusBadRequest, err) | ||
return | ||
} | ||
} | ||
|
||
type EventSource interface { | ||
ListEvent(ctx context.Context, opts ListOptions) (EventList, error) | ||
} | ||
|
||
type EventList struct { | ||
Items []Event | ||
} | ||
|
||
type Event struct { | ||
// Name of event, it should be shown on dashboard | ||
Name string `json:"name"` | ||
// Type of event. All events can be grouped by the type. | ||
Type EventType `json:"type"` | ||
// Metrics is the metrical data about this event | ||
Metrics EventMetrics `json:"metrics"` | ||
} | ||
|
||
type EventType string | ||
|
||
type EventMetrics struct { | ||
Count int64 `json:"count"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package backend | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
func TestEvent(t *testing.T) { | ||
events := EventList{Items: []Event{ | ||
{Name: "foo", Type: EventType("foo"), Metrics: EventMetrics{ | ||
Count: 1, | ||
}}, | ||
{Name: "bar", Type: EventType("bar"), Metrics: EventMetrics{ | ||
Count: 1, | ||
}}, | ||
}} | ||
raw, err := json.Marshal(events) | ||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
fmt.Println(string(raw)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package backend | ||
|
||
import ( | ||
restful "github.com/emicklei/go-restful/v3" | ||
) | ||
|
||
func WebService(event EventSource) *restful.WebService { | ||
ws := new(restful.WebService) | ||
ws.Path("/api") | ||
ws.Consumes(restful.MIME_JSON) | ||
ws.Produces(restful.MIME_JSON) // you can specify this per route as well | ||
|
||
AddEventService(ws, event) | ||
return ws | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.