From 46d785d695e0ea0e494677887ecf2c37a715e66c Mon Sep 17 00:00:00 2001 From: jplanckeel Date: Mon, 2 Feb 2026 10:59:18 +0100 Subject: [PATCH] feat: add api stats --- generated/openapiv2/apidocs.swagger.json | 416 ++++++++++- generated/proto/event/v1alpha1/event.pb.go | 651 +++++++++++++++-- generated/proto/event/v1alpha1/event.pb.gw.go | 188 ++++- .../proto/event/v1alpha1/event.pb.validate.go | 675 ++++++++++++++++++ .../proto/event/v1alpha1/event_grpc.pb.go | 100 ++- internal/stores/event.go | 59 ++ internal/utils/utils.go | 79 +- internal/utils/utils_test.go | 159 +++++ proto/event/v1alpha1/event.proto | 67 ++ server/event.go | 175 +++++ server/tracker.code-workspace | 32 + 11 files changed, 2461 insertions(+), 140 deletions(-) create mode 100644 server/tracker.code-workspace diff --git a/generated/openapiv2/apidocs.swagger.json b/generated/openapiv2/apidocs.swagger.json index 586b545..ae41456 100644 --- a/generated/openapiv2/apidocs.swagger.json +++ b/generated/openapiv2/apidocs.swagger.json @@ -35,7 +35,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -63,7 +63,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -91,7 +91,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -124,7 +124,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -170,7 +170,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -210,7 +210,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -249,7 +249,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -287,7 +287,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -317,7 +317,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -349,7 +349,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -377,7 +377,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -414,7 +414,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -457,7 +457,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -497,7 +497,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -536,7 +536,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -574,7 +574,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -692,6 +692,295 @@ ] } }, + "/api/v1alpha1/events/stats": { + "get": { + "summary": "Get event statistics count with filters", + "operationId": "EventService_GetEventStats", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1alpha1GetEventStatsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/googleRpcStatus" + } + } + }, + "parameters": [ + { + "name": "start_date", + "description": "Required: start date for the period (format: 2006-01-02 or ISO8601)", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "end_date", + "description": "Required: end date for the period (format: 2006-01-02 or ISO8601)", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "environments", + "description": "Optional filters", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "ENVIRONMENT_UNSPECIFIED", + "development", + "integration", + "TNR", + "UAT", + "recette", + "preproduction", + "production", + "mco" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "impact", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "priorities", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "PRIORITY_UNSPECIFIED", + "P1", + "P2", + "P3", + "P4", + "P5" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "types", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "TYPE_UNSPECIFIED", + "deployment", + "operation", + "drift", + "incident", + "rpa_usage" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "statuses", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "STATUS_UNSPECIFIED", + "start", + "failure", + "success", + "warning", + "error", + "snapshot", + "user_update", + "recommandation", + "open", + "close", + "done", + "in_progress", + "planned" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "source", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "service", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "EventService" + ] + } + }, + "/api/v1alpha1/events/stats/monthly": { + "get": { + "summary": "Get event statistics aggregated by month", + "operationId": "EventService_GetEventStatsByMonth", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1alpha1GetEventStatsByMonthResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/googleRpcStatus" + } + } + }, + "parameters": [ + { + "name": "start_date", + "description": "Required: start date for the period (format: 2006-01-02 or ISO8601)", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "end_date", + "description": "Required: end date for the period (format: 2006-01-02 or ISO8601)", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "environments", + "description": "Optional filters", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "ENVIRONMENT_UNSPECIFIED", + "development", + "integration", + "TNR", + "UAT", + "recette", + "preproduction", + "production", + "mco" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "impact", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "priorities", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "PRIORITY_UNSPECIFIED", + "P1", + "P2", + "P3", + "P4", + "P5" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "types", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "TYPE_UNSPECIFIED", + "deployment", + "operation", + "drift", + "incident", + "rpa_usage" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "statuses", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "STATUS_UNSPECIFIED", + "start", + "failure", + "success", + "warning", + "error", + "snapshot", + "user_update", + "recommandation", + "open", + "close", + "done", + "in_progress", + "planned" + ] + }, + "collectionFormat": "multi" + }, + { + "name": "source", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "service", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "group_by_service", + "description": "Group by service in addition to month", + "in": "query", + "required": false, + "type": "boolean" + } + ], + "tags": [ + "EventService" + ] + } + }, "/api/v1alpha1/events/today": { "get": { "operationId": "EventService_TodayEvents", @@ -705,7 +994,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -743,7 +1032,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -775,7 +1064,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -803,7 +1092,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -841,7 +1130,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -879,7 +1168,7 @@ "default": { "description": "An unexpected error response.", "schema": { - "$ref": "#/definitions/googlerpcStatus" + "$ref": "#/definitions/googleRpcStatus" } } }, @@ -979,7 +1268,7 @@ } } }, - "eventv1alpha1Status": { + "eventV1alpha1Status": { "type": "string", "enum": [ "STATUS_UNSPECIFIED", @@ -999,7 +1288,7 @@ ], "default": "STATUS_UNSPECIFIED" }, - "googlerpcStatus": { + "googleRpcStatus": { "type": "object", "properties": { "code": { @@ -1027,7 +1316,7 @@ }, "additionalProperties": {} }, - "trackercatalogv1alpha1Type": { + "trackerCatalogV1alpha1Type": { "type": "string", "enum": [ "TYPE_UNSPECIFIED", @@ -1041,7 +1330,7 @@ ], "default": "TYPE_UNSPECIFIED" }, - "trackereventv1alpha1Type": { + "trackerEventV1alpha1Type": { "type": "string", "enum": [ "TYPE_UNSPECIFIED", @@ -1078,7 +1367,7 @@ "type": "string" }, "type": { - "$ref": "#/definitions/trackercatalogv1alpha1Type" + "$ref": "#/definitions/trackerCatalogV1alpha1Type" }, "languages": { "$ref": "#/definitions/v1alpha1Languages" @@ -1346,7 +1635,7 @@ "type": "string" }, "type": { - "$ref": "#/definitions/trackercatalogv1alpha1Type" + "$ref": "#/definitions/trackerCatalogV1alpha1Type" }, "languages": { "$ref": "#/definitions/v1alpha1Languages" @@ -1508,7 +1797,7 @@ "type": "string" }, "type": { - "$ref": "#/definitions/trackercatalogv1alpha1Type" + "$ref": "#/definitions/trackerCatalogV1alpha1Type" }, "projects_using": { "type": "integer", @@ -1533,7 +1822,7 @@ "type": "string" }, "type": { - "$ref": "#/definitions/trackercatalogv1alpha1Type" + "$ref": "#/definitions/trackerCatalogV1alpha1Type" }, "current_version": { "type": "string", @@ -1606,7 +1895,7 @@ "type": "string" }, "type": { - "$ref": "#/definitions/trackereventv1alpha1Type" + "$ref": "#/definitions/trackerEventV1alpha1Type" }, "priority": { "$ref": "#/definitions/v1alpha1Priority" @@ -1618,7 +1907,7 @@ "type": "string" }, "status": { - "$ref": "#/definitions/eventv1alpha1Status" + "$ref": "#/definitions/eventV1alpha1Status" }, "environment": { "$ref": "#/definitions/v1alpha1Environment" @@ -1716,6 +2005,45 @@ } } }, + "v1alpha1GetEventStatsByMonthResponse": { + "type": "object", + "properties": { + "stats": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1alpha1MonthlyStats" + } + }, + "total_count": { + "type": "string", + "format": "uint64" + }, + "start_date": { + "type": "string" + }, + "end_date": { + "type": "string" + } + }, + "title": "Response for event statistics by month" + }, + "v1alpha1GetEventStatsResponse": { + "type": "object", + "properties": { + "total_count": { + "type": "string", + "format": "uint64" + }, + "start_date": { + "type": "string" + }, + "end_date": { + "type": "string" + } + }, + "title": "Response for event statistics count" + }, "v1alpha1GetLockResponse": { "type": "object", "properties": { @@ -1924,6 +2252,28 @@ } } }, + "v1alpha1MonthlyStats": { + "type": "object", + "properties": { + "year": { + "type": "integer", + "format": "int32" + }, + "month": { + "type": "integer", + "format": "int32" + }, + "count": { + "type": "string", + "format": "uint64" + }, + "service": { + "type": "string", + "title": "Only populated if group_by_service is true" + } + }, + "title": "Monthly statistics entry" + }, "v1alpha1Platform": { "type": "string", "enum": [ @@ -2129,7 +2479,7 @@ "title": "Name of the deliverable (package, chart, container, module)" }, "type": { - "$ref": "#/definitions/trackercatalogv1alpha1Type", + "$ref": "#/definitions/trackerCatalogV1alpha1Type", "title": "Type of deliverable (package, chart, container, module)" }, "version_used": { diff --git a/generated/proto/event/v1alpha1/event.pb.go b/generated/proto/event/v1alpha1/event.pb.go index f61e57c..2dbaf8e 100644 --- a/generated/proto/event/v1alpha1/event.pb.go +++ b/generated/proto/event/v1alpha1/event.pb.go @@ -1919,6 +1919,438 @@ func (x *AddSlackIdResponse) GetEvent() *Event { return nil } +// Request for event statistics count +type GetEventStatsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required: start date for the period (format: 2006-01-02 or ISO8601) + StartDate string `protobuf:"bytes,1,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"` + // Required: end date for the period (format: 2006-01-02 or ISO8601) + EndDate string `protobuf:"bytes,2,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"` + // Optional filters + Environments []Environment `protobuf:"varint,3,rep,packed,name=environments,proto3,enum=tracker.event.v1alpha1.Environment" json:"environments,omitempty"` + Impact *wrapperspb.BoolValue `protobuf:"bytes,4,opt,name=impact,proto3" json:"impact,omitempty"` + Priorities []Priority `protobuf:"varint,5,rep,packed,name=priorities,proto3,enum=tracker.event.v1alpha1.Priority" json:"priorities,omitempty"` + Types []Type `protobuf:"varint,6,rep,packed,name=types,proto3,enum=tracker.event.v1alpha1.Type" json:"types,omitempty"` + Statuses []Status `protobuf:"varint,7,rep,packed,name=statuses,proto3,enum=tracker.event.v1alpha1.Status" json:"statuses,omitempty"` + Source string `protobuf:"bytes,8,opt,name=source,proto3" json:"source,omitempty"` + Service string `protobuf:"bytes,9,opt,name=service,proto3" json:"service,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEventStatsRequest) Reset() { + *x = GetEventStatsRequest{} + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEventStatsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventStatsRequest) ProtoMessage() {} + +func (x *GetEventStatsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEventStatsRequest.ProtoReflect.Descriptor instead. +func (*GetEventStatsRequest) Descriptor() ([]byte, []int) { + return file_proto_event_v1alpha1_event_proto_rawDescGZIP(), []int{25} +} + +func (x *GetEventStatsRequest) GetStartDate() string { + if x != nil { + return x.StartDate + } + return "" +} + +func (x *GetEventStatsRequest) GetEndDate() string { + if x != nil { + return x.EndDate + } + return "" +} + +func (x *GetEventStatsRequest) GetEnvironments() []Environment { + if x != nil { + return x.Environments + } + return nil +} + +func (x *GetEventStatsRequest) GetImpact() *wrapperspb.BoolValue { + if x != nil { + return x.Impact + } + return nil +} + +func (x *GetEventStatsRequest) GetPriorities() []Priority { + if x != nil { + return x.Priorities + } + return nil +} + +func (x *GetEventStatsRequest) GetTypes() []Type { + if x != nil { + return x.Types + } + return nil +} + +func (x *GetEventStatsRequest) GetStatuses() []Status { + if x != nil { + return x.Statuses + } + return nil +} + +func (x *GetEventStatsRequest) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *GetEventStatsRequest) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +// Response for event statistics count +type GetEventStatsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TotalCount uint64 `protobuf:"varint,1,opt,name=total_count,json=totalCount,proto3" json:"total_count,omitempty"` + StartDate string `protobuf:"bytes,2,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"` + EndDate string `protobuf:"bytes,3,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEventStatsResponse) Reset() { + *x = GetEventStatsResponse{} + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEventStatsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventStatsResponse) ProtoMessage() {} + +func (x *GetEventStatsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEventStatsResponse.ProtoReflect.Descriptor instead. +func (*GetEventStatsResponse) Descriptor() ([]byte, []int) { + return file_proto_event_v1alpha1_event_proto_rawDescGZIP(), []int{26} +} + +func (x *GetEventStatsResponse) GetTotalCount() uint64 { + if x != nil { + return x.TotalCount + } + return 0 +} + +func (x *GetEventStatsResponse) GetStartDate() string { + if x != nil { + return x.StartDate + } + return "" +} + +func (x *GetEventStatsResponse) GetEndDate() string { + if x != nil { + return x.EndDate + } + return "" +} + +// Request for event statistics by month +type GetEventStatsByMonthRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Required: start date for the period (format: 2006-01-02 or ISO8601) + StartDate string `protobuf:"bytes,1,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"` + // Required: end date for the period (format: 2006-01-02 or ISO8601) + EndDate string `protobuf:"bytes,2,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"` + // Optional filters + Environments []Environment `protobuf:"varint,3,rep,packed,name=environments,proto3,enum=tracker.event.v1alpha1.Environment" json:"environments,omitempty"` + Impact *wrapperspb.BoolValue `protobuf:"bytes,4,opt,name=impact,proto3" json:"impact,omitempty"` + Priorities []Priority `protobuf:"varint,5,rep,packed,name=priorities,proto3,enum=tracker.event.v1alpha1.Priority" json:"priorities,omitempty"` + Types []Type `protobuf:"varint,6,rep,packed,name=types,proto3,enum=tracker.event.v1alpha1.Type" json:"types,omitempty"` + Statuses []Status `protobuf:"varint,7,rep,packed,name=statuses,proto3,enum=tracker.event.v1alpha1.Status" json:"statuses,omitempty"` + Source string `protobuf:"bytes,8,opt,name=source,proto3" json:"source,omitempty"` + Service string `protobuf:"bytes,9,opt,name=service,proto3" json:"service,omitempty"` + // Group by service in addition to month + GroupByService bool `protobuf:"varint,10,opt,name=group_by_service,json=groupByService,proto3" json:"group_by_service,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEventStatsByMonthRequest) Reset() { + *x = GetEventStatsByMonthRequest{} + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEventStatsByMonthRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventStatsByMonthRequest) ProtoMessage() {} + +func (x *GetEventStatsByMonthRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEventStatsByMonthRequest.ProtoReflect.Descriptor instead. +func (*GetEventStatsByMonthRequest) Descriptor() ([]byte, []int) { + return file_proto_event_v1alpha1_event_proto_rawDescGZIP(), []int{27} +} + +func (x *GetEventStatsByMonthRequest) GetStartDate() string { + if x != nil { + return x.StartDate + } + return "" +} + +func (x *GetEventStatsByMonthRequest) GetEndDate() string { + if x != nil { + return x.EndDate + } + return "" +} + +func (x *GetEventStatsByMonthRequest) GetEnvironments() []Environment { + if x != nil { + return x.Environments + } + return nil +} + +func (x *GetEventStatsByMonthRequest) GetImpact() *wrapperspb.BoolValue { + if x != nil { + return x.Impact + } + return nil +} + +func (x *GetEventStatsByMonthRequest) GetPriorities() []Priority { + if x != nil { + return x.Priorities + } + return nil +} + +func (x *GetEventStatsByMonthRequest) GetTypes() []Type { + if x != nil { + return x.Types + } + return nil +} + +func (x *GetEventStatsByMonthRequest) GetStatuses() []Status { + if x != nil { + return x.Statuses + } + return nil +} + +func (x *GetEventStatsByMonthRequest) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *GetEventStatsByMonthRequest) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +func (x *GetEventStatsByMonthRequest) GetGroupByService() bool { + if x != nil { + return x.GroupByService + } + return false +} + +// Monthly statistics entry +type MonthlyStats struct { + state protoimpl.MessageState `protogen:"open.v1"` + Year int32 `protobuf:"varint,1,opt,name=year,proto3" json:"year,omitempty"` + Month int32 `protobuf:"varint,2,opt,name=month,proto3" json:"month,omitempty"` + Count uint64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + Service string `protobuf:"bytes,4,opt,name=service,proto3" json:"service,omitempty"` // Only populated if group_by_service is true + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MonthlyStats) Reset() { + *x = MonthlyStats{} + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MonthlyStats) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MonthlyStats) ProtoMessage() {} + +func (x *MonthlyStats) ProtoReflect() protoreflect.Message { + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MonthlyStats.ProtoReflect.Descriptor instead. +func (*MonthlyStats) Descriptor() ([]byte, []int) { + return file_proto_event_v1alpha1_event_proto_rawDescGZIP(), []int{28} +} + +func (x *MonthlyStats) GetYear() int32 { + if x != nil { + return x.Year + } + return 0 +} + +func (x *MonthlyStats) GetMonth() int32 { + if x != nil { + return x.Month + } + return 0 +} + +func (x *MonthlyStats) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *MonthlyStats) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +// Response for event statistics by month +type GetEventStatsByMonthResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Stats []*MonthlyStats `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats,omitempty"` + TotalCount uint64 `protobuf:"varint,2,opt,name=total_count,json=totalCount,proto3" json:"total_count,omitempty"` + StartDate string `protobuf:"bytes,3,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"` + EndDate string `protobuf:"bytes,4,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEventStatsByMonthResponse) Reset() { + *x = GetEventStatsByMonthResponse{} + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEventStatsByMonthResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventStatsByMonthResponse) ProtoMessage() {} + +func (x *GetEventStatsByMonthResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_event_v1alpha1_event_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEventStatsByMonthResponse.ProtoReflect.Descriptor instead. +func (*GetEventStatsByMonthResponse) Descriptor() ([]byte, []int) { + return file_proto_event_v1alpha1_event_proto_rawDescGZIP(), []int{29} +} + +func (x *GetEventStatsByMonthResponse) GetStats() []*MonthlyStats { + if x != nil { + return x.Stats + } + return nil +} + +func (x *GetEventStatsByMonthResponse) GetTotalCount() uint64 { + if x != nil { + return x.TotalCount + } + return 0 +} + +func (x *GetEventStatsByMonthResponse) GetStartDate() string { + if x != nil { + return x.StartDate + } + return "" +} + +func (x *GetEventStatsByMonthResponse) GetEndDate() string { + if x != nil { + return x.EndDate + } + return "" +} + var File_proto_event_v1alpha1_event_proto protoreflect.FileDescriptor const file_proto_event_v1alpha1_event_proto_rawDesc = "" + @@ -2047,7 +2479,53 @@ const file_proto_event_v1alpha1_event_proto_rawDesc = "" + "\x02id\x18\x01 \x01(\tB\b\xfaB\x05r\x03\xb0\x01\x01R\x02id\x12\x19\n" + "\bslack_id\x18\x02 \x01(\tR\aslackId\"I\n" + "\x12AddSlackIdResponse\x123\n" + - "\x05event\x18\x01 \x01(\v2\x1d.tracker.event.v1alpha1.EventR\x05event*c\n" + + "\x05event\x18\x01 \x01(\v2\x1d.tracker.event.v1alpha1.EventR\x05event\"\xc3\x03\n" + + "\x14GetEventStatsRequest\x12&\n" + + "\n" + + "start_date\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\tstartDate\x12\"\n" + + "\bend_date\x18\x02 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\aendDate\x12G\n" + + "\fenvironments\x18\x03 \x03(\x0e2#.tracker.event.v1alpha1.EnvironmentR\fenvironments\x122\n" + + "\x06impact\x18\x04 \x01(\v2\x1a.google.protobuf.BoolValueR\x06impact\x12@\n" + + "\n" + + "priorities\x18\x05 \x03(\x0e2 .tracker.event.v1alpha1.PriorityR\n" + + "priorities\x122\n" + + "\x05types\x18\x06 \x03(\x0e2\x1c.tracker.event.v1alpha1.TypeR\x05types\x12:\n" + + "\bstatuses\x18\a \x03(\x0e2\x1e.tracker.event.v1alpha1.StatusR\bstatuses\x12\x16\n" + + "\x06source\x18\b \x01(\tR\x06source\x12\x18\n" + + "\aservice\x18\t \x01(\tR\aservice\"r\n" + + "\x15GetEventStatsResponse\x12\x1f\n" + + "\vtotal_count\x18\x01 \x01(\x04R\n" + + "totalCount\x12\x1d\n" + + "\n" + + "start_date\x18\x02 \x01(\tR\tstartDate\x12\x19\n" + + "\bend_date\x18\x03 \x01(\tR\aendDate\"\xf4\x03\n" + + "\x1bGetEventStatsByMonthRequest\x12&\n" + + "\n" + + "start_date\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\tstartDate\x12\"\n" + + "\bend_date\x18\x02 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\aendDate\x12G\n" + + "\fenvironments\x18\x03 \x03(\x0e2#.tracker.event.v1alpha1.EnvironmentR\fenvironments\x122\n" + + "\x06impact\x18\x04 \x01(\v2\x1a.google.protobuf.BoolValueR\x06impact\x12@\n" + + "\n" + + "priorities\x18\x05 \x03(\x0e2 .tracker.event.v1alpha1.PriorityR\n" + + "priorities\x122\n" + + "\x05types\x18\x06 \x03(\x0e2\x1c.tracker.event.v1alpha1.TypeR\x05types\x12:\n" + + "\bstatuses\x18\a \x03(\x0e2\x1e.tracker.event.v1alpha1.StatusR\bstatuses\x12\x16\n" + + "\x06source\x18\b \x01(\tR\x06source\x12\x18\n" + + "\aservice\x18\t \x01(\tR\aservice\x12(\n" + + "\x10group_by_service\x18\n" + + " \x01(\bR\x0egroupByService\"h\n" + + "\fMonthlyStats\x12\x12\n" + + "\x04year\x18\x01 \x01(\x05R\x04year\x12\x14\n" + + "\x05month\x18\x02 \x01(\x05R\x05month\x12\x14\n" + + "\x05count\x18\x03 \x01(\x04R\x05count\x12\x18\n" + + "\aservice\x18\x04 \x01(\tR\aservice\"\xb5\x01\n" + + "\x1cGetEventStatsByMonthResponse\x12:\n" + + "\x05stats\x18\x01 \x03(\v2$.tracker.event.v1alpha1.MonthlyStatsR\x05stats\x12\x1f\n" + + "\vtotal_count\x18\x02 \x01(\x04R\n" + + "totalCount\x12\x1d\n" + + "\n" + + "start_date\x18\x03 \x01(\tR\tstartDate\x12\x19\n" + + "\bend_date\x18\x04 \x01(\tR\aendDate*c\n" + "\x04Type\x12\x14\n" + "\x10TYPE_UNSPECIFIED\x10\x00\x12\x0e\n" + "\n" + @@ -2103,7 +2581,7 @@ const file_proto_event_v1alpha1_event_proto_rawDesc = "" + "\x06linked\x10\a\x12\n" + "\n" + "\x06locked\x10\b\x12\f\n" + - "\bunlocked\x10\t2\xb6\v\n" + + "\bunlocked\x10\t2\xf9\r\n" + "\fEventService\x12\x86\x01\n" + "\vCreateEvent\x12*.tracker.event.v1alpha1.CreateEventRequest\x1a+.tracker.event.v1alpha1.CreateEventResponse\"\x1e\x82\xd3\xe4\x93\x02\x18:\x01*\"\x13/api/v1alpha1/event\x12\x86\x01\n" + "\vUpdateEvent\x12*.tracker.event.v1alpha1.UpdateEventRequest\x1a+.tracker.event.v1alpha1.UpdateEventResponse\"\x1e\x82\xd3\xe4\x93\x02\x18:\x01*\x1a\x13/api/v1alpha1/event\x12\x89\x01\n" + @@ -2116,7 +2594,9 @@ const file_proto_event_v1alpha1_event_proto_rawDesc = "" + "\x11AddChangelogEntry\x120.tracker.event.v1alpha1.AddChangelogEntryRequest\x1a1.tracker.event.v1alpha1.AddChangelogEntryResponse\"-\x82\xd3\xe4\x93\x02':\x01*\"\"/api/v1alpha1/event/{id}/changelog\x12\xa4\x01\n" + "\x11GetEventChangelog\x120.tracker.event.v1alpha1.GetEventChangelogRequest\x1a1.tracker.event.v1alpha1.GetEventChangelogResponse\"*\x82\xd3\xe4\x93\x02$\x12\"/api/v1alpha1/event/{id}/changelog\x12\x8e\x01\n" + "\n" + - "AddSlackId\x12).tracker.event.v1alpha1.AddSlackIdRequest\x1a*.tracker.event.v1alpha1.AddSlackIdResponse\")\x82\xd3\xe4\x93\x02#:\x01*\"\x1e/api/v1alpha1/event/{id}/slackB\x16Z\x14proto/event/v1alpha1b\x06proto3" + "AddSlackId\x12).tracker.event.v1alpha1.AddSlackIdRequest\x1a*.tracker.event.v1alpha1.AddSlackIdResponse\")\x82\xd3\xe4\x93\x02#:\x01*\"\x1e/api/v1alpha1/event/{id}/slack\x12\x90\x01\n" + + "\rGetEventStats\x12,.tracker.event.v1alpha1.GetEventStatsRequest\x1a-.tracker.event.v1alpha1.GetEventStatsResponse\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/api/v1alpha1/events/stats\x12\xad\x01\n" + + "\x14GetEventStatsByMonth\x123.tracker.event.v1alpha1.GetEventStatsByMonthRequest\x1a4.tracker.event.v1alpha1.GetEventStatsByMonthResponse\"*\x82\xd3\xe4\x93\x02$\x12\"/api/v1alpha1/events/stats/monthlyB\x16Z\x14proto/event/v1alpha1b\x06proto3" var ( file_proto_event_v1alpha1_event_proto_rawDescOnce sync.Once @@ -2131,53 +2611,59 @@ func file_proto_event_v1alpha1_event_proto_rawDescGZIP() []byte { } var file_proto_event_v1alpha1_event_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_proto_event_v1alpha1_event_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_proto_event_v1alpha1_event_proto_msgTypes = make([]protoimpl.MessageInfo, 30) var file_proto_event_v1alpha1_event_proto_goTypes = []any{ - (Type)(0), // 0: tracker.event.v1alpha1.Type - (Priority)(0), // 1: tracker.event.v1alpha1.Priority - (Status)(0), // 2: tracker.event.v1alpha1.Status - (Environment)(0), // 3: tracker.event.v1alpha1.Environment - (ChangeType)(0), // 4: tracker.event.v1alpha1.ChangeType - (*EventAttributes)(nil), // 5: tracker.event.v1alpha1.EventAttributes - (*EventMetadata)(nil), // 6: tracker.event.v1alpha1.EventMetadata - (*EventLinks)(nil), // 7: tracker.event.v1alpha1.EventLinks - (*ChangelogEntry)(nil), // 8: tracker.event.v1alpha1.ChangelogEntry - (*Event)(nil), // 9: tracker.event.v1alpha1.Event - (*CreateEventRequest)(nil), // 10: tracker.event.v1alpha1.CreateEventRequest - (*CreateEventResponse)(nil), // 11: tracker.event.v1alpha1.CreateEventResponse - (*GetEventRequest)(nil), // 12: tracker.event.v1alpha1.GetEventRequest - (*GetEventResponse)(nil), // 13: tracker.event.v1alpha1.GetEventResponse - (*SearchEventsRequest)(nil), // 14: tracker.event.v1alpha1.SearchEventsRequest - (*SearchEventsResponse)(nil), // 15: tracker.event.v1alpha1.SearchEventsResponse - (*ListEventsRequest)(nil), // 16: tracker.event.v1alpha1.ListEventsRequest - (*ListEventsResponse)(nil), // 17: tracker.event.v1alpha1.ListEventsResponse - (*TodayEventsRequest)(nil), // 18: tracker.event.v1alpha1.TodayEventsRequest - (*TodayEventsResponse)(nil), // 19: tracker.event.v1alpha1.TodayEventsResponse - (*AddChangelogEntryRequest)(nil), // 20: tracker.event.v1alpha1.AddChangelogEntryRequest - (*AddChangelogEntryResponse)(nil), // 21: tracker.event.v1alpha1.AddChangelogEntryResponse - (*GetEventChangelogRequest)(nil), // 22: tracker.event.v1alpha1.GetEventChangelogRequest - (*GetEventChangelogResponse)(nil), // 23: tracker.event.v1alpha1.GetEventChangelogResponse - (*UpdateEventRequest)(nil), // 24: tracker.event.v1alpha1.UpdateEventRequest - (*UpdateEventResponse)(nil), // 25: tracker.event.v1alpha1.UpdateEventResponse - (*DeleteEventRequest)(nil), // 26: tracker.event.v1alpha1.DeleteEventRequest - (*DeleteEventResponse)(nil), // 27: tracker.event.v1alpha1.DeleteEventResponse - (*AddSlackIdRequest)(nil), // 28: tracker.event.v1alpha1.AddSlackIdRequest - (*AddSlackIdResponse)(nil), // 29: tracker.event.v1alpha1.AddSlackIdResponse - (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 31: google.protobuf.Duration - (*wrapperspb.UInt32Value)(nil), // 32: google.protobuf.UInt32Value - (*wrapperspb.Int32Value)(nil), // 33: google.protobuf.Int32Value + (Type)(0), // 0: tracker.event.v1alpha1.Type + (Priority)(0), // 1: tracker.event.v1alpha1.Priority + (Status)(0), // 2: tracker.event.v1alpha1.Status + (Environment)(0), // 3: tracker.event.v1alpha1.Environment + (ChangeType)(0), // 4: tracker.event.v1alpha1.ChangeType + (*EventAttributes)(nil), // 5: tracker.event.v1alpha1.EventAttributes + (*EventMetadata)(nil), // 6: tracker.event.v1alpha1.EventMetadata + (*EventLinks)(nil), // 7: tracker.event.v1alpha1.EventLinks + (*ChangelogEntry)(nil), // 8: tracker.event.v1alpha1.ChangelogEntry + (*Event)(nil), // 9: tracker.event.v1alpha1.Event + (*CreateEventRequest)(nil), // 10: tracker.event.v1alpha1.CreateEventRequest + (*CreateEventResponse)(nil), // 11: tracker.event.v1alpha1.CreateEventResponse + (*GetEventRequest)(nil), // 12: tracker.event.v1alpha1.GetEventRequest + (*GetEventResponse)(nil), // 13: tracker.event.v1alpha1.GetEventResponse + (*SearchEventsRequest)(nil), // 14: tracker.event.v1alpha1.SearchEventsRequest + (*SearchEventsResponse)(nil), // 15: tracker.event.v1alpha1.SearchEventsResponse + (*ListEventsRequest)(nil), // 16: tracker.event.v1alpha1.ListEventsRequest + (*ListEventsResponse)(nil), // 17: tracker.event.v1alpha1.ListEventsResponse + (*TodayEventsRequest)(nil), // 18: tracker.event.v1alpha1.TodayEventsRequest + (*TodayEventsResponse)(nil), // 19: tracker.event.v1alpha1.TodayEventsResponse + (*AddChangelogEntryRequest)(nil), // 20: tracker.event.v1alpha1.AddChangelogEntryRequest + (*AddChangelogEntryResponse)(nil), // 21: tracker.event.v1alpha1.AddChangelogEntryResponse + (*GetEventChangelogRequest)(nil), // 22: tracker.event.v1alpha1.GetEventChangelogRequest + (*GetEventChangelogResponse)(nil), // 23: tracker.event.v1alpha1.GetEventChangelogResponse + (*UpdateEventRequest)(nil), // 24: tracker.event.v1alpha1.UpdateEventRequest + (*UpdateEventResponse)(nil), // 25: tracker.event.v1alpha1.UpdateEventResponse + (*DeleteEventRequest)(nil), // 26: tracker.event.v1alpha1.DeleteEventRequest + (*DeleteEventResponse)(nil), // 27: tracker.event.v1alpha1.DeleteEventResponse + (*AddSlackIdRequest)(nil), // 28: tracker.event.v1alpha1.AddSlackIdRequest + (*AddSlackIdResponse)(nil), // 29: tracker.event.v1alpha1.AddSlackIdResponse + (*GetEventStatsRequest)(nil), // 30: tracker.event.v1alpha1.GetEventStatsRequest + (*GetEventStatsResponse)(nil), // 31: tracker.event.v1alpha1.GetEventStatsResponse + (*GetEventStatsByMonthRequest)(nil), // 32: tracker.event.v1alpha1.GetEventStatsByMonthRequest + (*MonthlyStats)(nil), // 33: tracker.event.v1alpha1.MonthlyStats + (*GetEventStatsByMonthResponse)(nil), // 34: tracker.event.v1alpha1.GetEventStatsByMonthResponse + (*timestamppb.Timestamp)(nil), // 35: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 36: google.protobuf.Duration + (*wrapperspb.UInt32Value)(nil), // 37: google.protobuf.UInt32Value + (*wrapperspb.Int32Value)(nil), // 38: google.protobuf.Int32Value + (*wrapperspb.BoolValue)(nil), // 39: google.protobuf.BoolValue } var file_proto_event_v1alpha1_event_proto_depIdxs = []int32{ 0, // 0: tracker.event.v1alpha1.EventAttributes.type:type_name -> tracker.event.v1alpha1.Type 1, // 1: tracker.event.v1alpha1.EventAttributes.priority:type_name -> tracker.event.v1alpha1.Priority 2, // 2: tracker.event.v1alpha1.EventAttributes.status:type_name -> tracker.event.v1alpha1.Status 3, // 3: tracker.event.v1alpha1.EventAttributes.environment:type_name -> tracker.event.v1alpha1.Environment - 30, // 4: tracker.event.v1alpha1.EventAttributes.start_date:type_name -> google.protobuf.Timestamp - 30, // 5: tracker.event.v1alpha1.EventAttributes.end_date:type_name -> google.protobuf.Timestamp - 30, // 6: tracker.event.v1alpha1.EventMetadata.created_at:type_name -> google.protobuf.Timestamp - 31, // 7: tracker.event.v1alpha1.EventMetadata.duration:type_name -> google.protobuf.Duration - 30, // 8: tracker.event.v1alpha1.ChangelogEntry.timestamp:type_name -> google.protobuf.Timestamp + 35, // 4: tracker.event.v1alpha1.EventAttributes.start_date:type_name -> google.protobuf.Timestamp + 35, // 5: tracker.event.v1alpha1.EventAttributes.end_date:type_name -> google.protobuf.Timestamp + 35, // 6: tracker.event.v1alpha1.EventMetadata.created_at:type_name -> google.protobuf.Timestamp + 36, // 7: tracker.event.v1alpha1.EventMetadata.duration:type_name -> google.protobuf.Duration + 35, // 8: tracker.event.v1alpha1.ChangelogEntry.timestamp:type_name -> google.protobuf.Timestamp 4, // 9: tracker.event.v1alpha1.ChangelogEntry.change_type:type_name -> tracker.event.v1alpha1.ChangeType 5, // 10: tracker.event.v1alpha1.Event.attributes:type_name -> tracker.event.v1alpha1.EventAttributes 7, // 11: tracker.event.v1alpha1.Event.links:type_name -> tracker.event.v1alpha1.EventLinks @@ -2192,46 +2678,61 @@ var file_proto_event_v1alpha1_event_proto_depIdxs = []int32{ 2, // 20: tracker.event.v1alpha1.SearchEventsRequest.status:type_name -> tracker.event.v1alpha1.Status 3, // 21: tracker.event.v1alpha1.SearchEventsRequest.environment:type_name -> tracker.event.v1alpha1.Environment 9, // 22: tracker.event.v1alpha1.SearchEventsResponse.events:type_name -> tracker.event.v1alpha1.Event - 32, // 23: tracker.event.v1alpha1.ListEventsRequest.per_page:type_name -> google.protobuf.UInt32Value - 33, // 24: tracker.event.v1alpha1.ListEventsRequest.page:type_name -> google.protobuf.Int32Value + 37, // 23: tracker.event.v1alpha1.ListEventsRequest.per_page:type_name -> google.protobuf.UInt32Value + 38, // 24: tracker.event.v1alpha1.ListEventsRequest.page:type_name -> google.protobuf.Int32Value 9, // 25: tracker.event.v1alpha1.ListEventsResponse.events:type_name -> tracker.event.v1alpha1.Event - 32, // 26: tracker.event.v1alpha1.TodayEventsRequest.per_page:type_name -> google.protobuf.UInt32Value - 33, // 27: tracker.event.v1alpha1.TodayEventsRequest.page:type_name -> google.protobuf.Int32Value + 37, // 26: tracker.event.v1alpha1.TodayEventsRequest.per_page:type_name -> google.protobuf.UInt32Value + 38, // 27: tracker.event.v1alpha1.TodayEventsRequest.page:type_name -> google.protobuf.Int32Value 9, // 28: tracker.event.v1alpha1.TodayEventsResponse.events:type_name -> tracker.event.v1alpha1.Event 8, // 29: tracker.event.v1alpha1.AddChangelogEntryRequest.entry:type_name -> tracker.event.v1alpha1.ChangelogEntry 9, // 30: tracker.event.v1alpha1.AddChangelogEntryResponse.event:type_name -> tracker.event.v1alpha1.Event - 32, // 31: tracker.event.v1alpha1.GetEventChangelogRequest.per_page:type_name -> google.protobuf.UInt32Value - 33, // 32: tracker.event.v1alpha1.GetEventChangelogRequest.page:type_name -> google.protobuf.Int32Value + 37, // 31: tracker.event.v1alpha1.GetEventChangelogRequest.per_page:type_name -> google.protobuf.UInt32Value + 38, // 32: tracker.event.v1alpha1.GetEventChangelogRequest.page:type_name -> google.protobuf.Int32Value 8, // 33: tracker.event.v1alpha1.GetEventChangelogResponse.changelog:type_name -> tracker.event.v1alpha1.ChangelogEntry 5, // 34: tracker.event.v1alpha1.UpdateEventRequest.attributes:type_name -> tracker.event.v1alpha1.EventAttributes 7, // 35: tracker.event.v1alpha1.UpdateEventRequest.links:type_name -> tracker.event.v1alpha1.EventLinks 9, // 36: tracker.event.v1alpha1.UpdateEventResponse.event:type_name -> tracker.event.v1alpha1.Event 9, // 37: tracker.event.v1alpha1.AddSlackIdResponse.event:type_name -> tracker.event.v1alpha1.Event - 10, // 38: tracker.event.v1alpha1.EventService.CreateEvent:input_type -> tracker.event.v1alpha1.CreateEventRequest - 24, // 39: tracker.event.v1alpha1.EventService.UpdateEvent:input_type -> tracker.event.v1alpha1.UpdateEventRequest - 26, // 40: tracker.event.v1alpha1.EventService.DeleteEvents:input_type -> tracker.event.v1alpha1.DeleteEventRequest - 12, // 41: tracker.event.v1alpha1.EventService.GetEvent:input_type -> tracker.event.v1alpha1.GetEventRequest - 14, // 42: tracker.event.v1alpha1.EventService.SearchEvents:input_type -> tracker.event.v1alpha1.SearchEventsRequest - 16, // 43: tracker.event.v1alpha1.EventService.ListEvents:input_type -> tracker.event.v1alpha1.ListEventsRequest - 18, // 44: tracker.event.v1alpha1.EventService.TodayEvents:input_type -> tracker.event.v1alpha1.TodayEventsRequest - 20, // 45: tracker.event.v1alpha1.EventService.AddChangelogEntry:input_type -> tracker.event.v1alpha1.AddChangelogEntryRequest - 22, // 46: tracker.event.v1alpha1.EventService.GetEventChangelog:input_type -> tracker.event.v1alpha1.GetEventChangelogRequest - 28, // 47: tracker.event.v1alpha1.EventService.AddSlackId:input_type -> tracker.event.v1alpha1.AddSlackIdRequest - 11, // 48: tracker.event.v1alpha1.EventService.CreateEvent:output_type -> tracker.event.v1alpha1.CreateEventResponse - 25, // 49: tracker.event.v1alpha1.EventService.UpdateEvent:output_type -> tracker.event.v1alpha1.UpdateEventResponse - 27, // 50: tracker.event.v1alpha1.EventService.DeleteEvents:output_type -> tracker.event.v1alpha1.DeleteEventResponse - 13, // 51: tracker.event.v1alpha1.EventService.GetEvent:output_type -> tracker.event.v1alpha1.GetEventResponse - 15, // 52: tracker.event.v1alpha1.EventService.SearchEvents:output_type -> tracker.event.v1alpha1.SearchEventsResponse - 17, // 53: tracker.event.v1alpha1.EventService.ListEvents:output_type -> tracker.event.v1alpha1.ListEventsResponse - 19, // 54: tracker.event.v1alpha1.EventService.TodayEvents:output_type -> tracker.event.v1alpha1.TodayEventsResponse - 21, // 55: tracker.event.v1alpha1.EventService.AddChangelogEntry:output_type -> tracker.event.v1alpha1.AddChangelogEntryResponse - 23, // 56: tracker.event.v1alpha1.EventService.GetEventChangelog:output_type -> tracker.event.v1alpha1.GetEventChangelogResponse - 29, // 57: tracker.event.v1alpha1.EventService.AddSlackId:output_type -> tracker.event.v1alpha1.AddSlackIdResponse - 48, // [48:58] is the sub-list for method output_type - 38, // [38:48] is the sub-list for method input_type - 38, // [38:38] is the sub-list for extension type_name - 38, // [38:38] is the sub-list for extension extendee - 0, // [0:38] is the sub-list for field type_name + 3, // 38: tracker.event.v1alpha1.GetEventStatsRequest.environments:type_name -> tracker.event.v1alpha1.Environment + 39, // 39: tracker.event.v1alpha1.GetEventStatsRequest.impact:type_name -> google.protobuf.BoolValue + 1, // 40: tracker.event.v1alpha1.GetEventStatsRequest.priorities:type_name -> tracker.event.v1alpha1.Priority + 0, // 41: tracker.event.v1alpha1.GetEventStatsRequest.types:type_name -> tracker.event.v1alpha1.Type + 2, // 42: tracker.event.v1alpha1.GetEventStatsRequest.statuses:type_name -> tracker.event.v1alpha1.Status + 3, // 43: tracker.event.v1alpha1.GetEventStatsByMonthRequest.environments:type_name -> tracker.event.v1alpha1.Environment + 39, // 44: tracker.event.v1alpha1.GetEventStatsByMonthRequest.impact:type_name -> google.protobuf.BoolValue + 1, // 45: tracker.event.v1alpha1.GetEventStatsByMonthRequest.priorities:type_name -> tracker.event.v1alpha1.Priority + 0, // 46: tracker.event.v1alpha1.GetEventStatsByMonthRequest.types:type_name -> tracker.event.v1alpha1.Type + 2, // 47: tracker.event.v1alpha1.GetEventStatsByMonthRequest.statuses:type_name -> tracker.event.v1alpha1.Status + 33, // 48: tracker.event.v1alpha1.GetEventStatsByMonthResponse.stats:type_name -> tracker.event.v1alpha1.MonthlyStats + 10, // 49: tracker.event.v1alpha1.EventService.CreateEvent:input_type -> tracker.event.v1alpha1.CreateEventRequest + 24, // 50: tracker.event.v1alpha1.EventService.UpdateEvent:input_type -> tracker.event.v1alpha1.UpdateEventRequest + 26, // 51: tracker.event.v1alpha1.EventService.DeleteEvents:input_type -> tracker.event.v1alpha1.DeleteEventRequest + 12, // 52: tracker.event.v1alpha1.EventService.GetEvent:input_type -> tracker.event.v1alpha1.GetEventRequest + 14, // 53: tracker.event.v1alpha1.EventService.SearchEvents:input_type -> tracker.event.v1alpha1.SearchEventsRequest + 16, // 54: tracker.event.v1alpha1.EventService.ListEvents:input_type -> tracker.event.v1alpha1.ListEventsRequest + 18, // 55: tracker.event.v1alpha1.EventService.TodayEvents:input_type -> tracker.event.v1alpha1.TodayEventsRequest + 20, // 56: tracker.event.v1alpha1.EventService.AddChangelogEntry:input_type -> tracker.event.v1alpha1.AddChangelogEntryRequest + 22, // 57: tracker.event.v1alpha1.EventService.GetEventChangelog:input_type -> tracker.event.v1alpha1.GetEventChangelogRequest + 28, // 58: tracker.event.v1alpha1.EventService.AddSlackId:input_type -> tracker.event.v1alpha1.AddSlackIdRequest + 30, // 59: tracker.event.v1alpha1.EventService.GetEventStats:input_type -> tracker.event.v1alpha1.GetEventStatsRequest + 32, // 60: tracker.event.v1alpha1.EventService.GetEventStatsByMonth:input_type -> tracker.event.v1alpha1.GetEventStatsByMonthRequest + 11, // 61: tracker.event.v1alpha1.EventService.CreateEvent:output_type -> tracker.event.v1alpha1.CreateEventResponse + 25, // 62: tracker.event.v1alpha1.EventService.UpdateEvent:output_type -> tracker.event.v1alpha1.UpdateEventResponse + 27, // 63: tracker.event.v1alpha1.EventService.DeleteEvents:output_type -> tracker.event.v1alpha1.DeleteEventResponse + 13, // 64: tracker.event.v1alpha1.EventService.GetEvent:output_type -> tracker.event.v1alpha1.GetEventResponse + 15, // 65: tracker.event.v1alpha1.EventService.SearchEvents:output_type -> tracker.event.v1alpha1.SearchEventsResponse + 17, // 66: tracker.event.v1alpha1.EventService.ListEvents:output_type -> tracker.event.v1alpha1.ListEventsResponse + 19, // 67: tracker.event.v1alpha1.EventService.TodayEvents:output_type -> tracker.event.v1alpha1.TodayEventsResponse + 21, // 68: tracker.event.v1alpha1.EventService.AddChangelogEntry:output_type -> tracker.event.v1alpha1.AddChangelogEntryResponse + 23, // 69: tracker.event.v1alpha1.EventService.GetEventChangelog:output_type -> tracker.event.v1alpha1.GetEventChangelogResponse + 29, // 70: tracker.event.v1alpha1.EventService.AddSlackId:output_type -> tracker.event.v1alpha1.AddSlackIdResponse + 31, // 71: tracker.event.v1alpha1.EventService.GetEventStats:output_type -> tracker.event.v1alpha1.GetEventStatsResponse + 34, // 72: tracker.event.v1alpha1.EventService.GetEventStatsByMonth:output_type -> tracker.event.v1alpha1.GetEventStatsByMonthResponse + 61, // [61:73] is the sub-list for method output_type + 49, // [49:61] is the sub-list for method input_type + 49, // [49:49] is the sub-list for extension type_name + 49, // [49:49] is the sub-list for extension extendee + 0, // [0:49] is the sub-list for field type_name } func init() { file_proto_event_v1alpha1_event_proto_init() } @@ -2245,7 +2746,7 @@ func file_proto_event_v1alpha1_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_event_v1alpha1_event_proto_rawDesc), len(file_proto_event_v1alpha1_event_proto_rawDesc)), NumEnums: 5, - NumMessages: 25, + NumMessages: 30, NumExtensions: 0, NumServices: 1, }, diff --git a/generated/proto/event/v1alpha1/event.pb.gw.go b/generated/proto/event/v1alpha1/event.pb.gw.go index 1b33112..649237e 100644 --- a/generated/proto/event/v1alpha1/event.pb.gw.go +++ b/generated/proto/event/v1alpha1/event.pb.gw.go @@ -429,6 +429,76 @@ func local_request_EventService_AddSlackId_0(ctx context.Context, marshaler runt return msg, metadata, err } +var filter_EventService_GetEventStats_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + +func request_EventService_GetEventStats_0(ctx context.Context, marshaler runtime.Marshaler, client EventServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetEventStatsRequest + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_EventService_GetEventStats_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetEventStats(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EventService_GetEventStats_0(ctx context.Context, marshaler runtime.Marshaler, server EventServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetEventStatsRequest + metadata runtime.ServerMetadata + ) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_EventService_GetEventStats_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetEventStats(ctx, &protoReq) + return msg, metadata, err +} + +var filter_EventService_GetEventStatsByMonth_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + +func request_EventService_GetEventStatsByMonth_0(ctx context.Context, marshaler runtime.Marshaler, client EventServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetEventStatsByMonthRequest + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_EventService_GetEventStatsByMonth_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetEventStatsByMonth(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EventService_GetEventStatsByMonth_0(ctx context.Context, marshaler runtime.Marshaler, server EventServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetEventStatsByMonthRequest + metadata runtime.ServerMetadata + ) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_EventService_GetEventStatsByMonth_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetEventStatsByMonth(ctx, &protoReq) + return msg, metadata, err +} + // RegisterEventServiceHandlerServer registers the http handlers for service EventService to "mux". // UnaryRPC :call EventServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -635,6 +705,46 @@ func RegisterEventServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu } forward_EventService_AddSlackId_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_EventService_GetEventStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/tracker.event.v1alpha1.EventService/GetEventStats", runtime.WithHTTPPathPattern("/api/v1alpha1/events/stats")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EventService_GetEventStats_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_EventService_GetEventStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EventService_GetEventStatsByMonth_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/tracker.event.v1alpha1.EventService/GetEventStatsByMonth", runtime.WithHTTPPathPattern("/api/v1alpha1/events/stats/monthly")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EventService_GetEventStatsByMonth_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_EventService_GetEventStatsByMonth_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -845,31 +955,69 @@ func RegisterEventServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu } forward_EventService_AddSlackId_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_EventService_GetEventStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/tracker.event.v1alpha1.EventService/GetEventStats", runtime.WithHTTPPathPattern("/api/v1alpha1/events/stats")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EventService_GetEventStats_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_EventService_GetEventStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EventService_GetEventStatsByMonth_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/tracker.event.v1alpha1.EventService/GetEventStatsByMonth", runtime.WithHTTPPathPattern("/api/v1alpha1/events/stats/monthly")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EventService_GetEventStatsByMonth_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_EventService_GetEventStatsByMonth_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } var ( - pattern_EventService_CreateEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1alpha1", "event"}, "")) - pattern_EventService_UpdateEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1alpha1", "event"}, "")) - pattern_EventService_DeleteEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1alpha1", "event", "id"}, "")) - pattern_EventService_GetEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1alpha1", "event", "id"}, "")) - pattern_EventService_SearchEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "search"}, "")) - pattern_EventService_ListEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "list"}, "")) - pattern_EventService_TodayEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "today"}, "")) - pattern_EventService_AddChangelogEntry_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1alpha1", "event", "id", "changelog"}, "")) - pattern_EventService_GetEventChangelog_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1alpha1", "event", "id", "changelog"}, "")) - pattern_EventService_AddSlackId_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1alpha1", "event", "id", "slack"}, "")) + pattern_EventService_CreateEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1alpha1", "event"}, "")) + pattern_EventService_UpdateEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1alpha1", "event"}, "")) + pattern_EventService_DeleteEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1alpha1", "event", "id"}, "")) + pattern_EventService_GetEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1alpha1", "event", "id"}, "")) + pattern_EventService_SearchEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "search"}, "")) + pattern_EventService_ListEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "list"}, "")) + pattern_EventService_TodayEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "today"}, "")) + pattern_EventService_AddChangelogEntry_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1alpha1", "event", "id", "changelog"}, "")) + pattern_EventService_GetEventChangelog_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1alpha1", "event", "id", "changelog"}, "")) + pattern_EventService_AddSlackId_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1alpha1", "event", "id", "slack"}, "")) + pattern_EventService_GetEventStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1alpha1", "events", "stats"}, "")) + pattern_EventService_GetEventStatsByMonth_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"api", "v1alpha1", "events", "stats", "monthly"}, "")) ) var ( - forward_EventService_CreateEvent_0 = runtime.ForwardResponseMessage - forward_EventService_UpdateEvent_0 = runtime.ForwardResponseMessage - forward_EventService_DeleteEvents_0 = runtime.ForwardResponseMessage - forward_EventService_GetEvent_0 = runtime.ForwardResponseMessage - forward_EventService_SearchEvents_0 = runtime.ForwardResponseMessage - forward_EventService_ListEvents_0 = runtime.ForwardResponseMessage - forward_EventService_TodayEvents_0 = runtime.ForwardResponseMessage - forward_EventService_AddChangelogEntry_0 = runtime.ForwardResponseMessage - forward_EventService_GetEventChangelog_0 = runtime.ForwardResponseMessage - forward_EventService_AddSlackId_0 = runtime.ForwardResponseMessage + forward_EventService_CreateEvent_0 = runtime.ForwardResponseMessage + forward_EventService_UpdateEvent_0 = runtime.ForwardResponseMessage + forward_EventService_DeleteEvents_0 = runtime.ForwardResponseMessage + forward_EventService_GetEvent_0 = runtime.ForwardResponseMessage + forward_EventService_SearchEvents_0 = runtime.ForwardResponseMessage + forward_EventService_ListEvents_0 = runtime.ForwardResponseMessage + forward_EventService_TodayEvents_0 = runtime.ForwardResponseMessage + forward_EventService_AddChangelogEntry_0 = runtime.ForwardResponseMessage + forward_EventService_GetEventChangelog_0 = runtime.ForwardResponseMessage + forward_EventService_AddSlackId_0 = runtime.ForwardResponseMessage + forward_EventService_GetEventStats_0 = runtime.ForwardResponseMessage + forward_EventService_GetEventStatsByMonth_0 = runtime.ForwardResponseMessage ) diff --git a/generated/proto/event/v1alpha1/event.pb.validate.go b/generated/proto/event/v1alpha1/event.pb.validate.go index 57a9b56..502594a 100644 --- a/generated/proto/event/v1alpha1/event.pb.validate.go +++ b/generated/proto/event/v1alpha1/event.pb.validate.go @@ -3626,3 +3626,678 @@ var _ interface { Cause() error ErrorName() string } = AddSlackIdResponseValidationError{} + +// Validate checks the field values on GetEventStatsRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetEventStatsRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetEventStatsRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetEventStatsRequestMultiError, or nil if none found. +func (m *GetEventStatsRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetEventStatsRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if utf8.RuneCountInString(m.GetStartDate()) < 1 { + err := GetEventStatsRequestValidationError{ + field: "StartDate", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if utf8.RuneCountInString(m.GetEndDate()) < 1 { + err := GetEventStatsRequestValidationError{ + field: "EndDate", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetImpact()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetEventStatsRequestValidationError{ + field: "Impact", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetEventStatsRequestValidationError{ + field: "Impact", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetImpact()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetEventStatsRequestValidationError{ + field: "Impact", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Source + + // no validation rules for Service + + if len(errors) > 0 { + return GetEventStatsRequestMultiError(errors) + } + + return nil +} + +// GetEventStatsRequestMultiError is an error wrapping multiple validation +// errors returned by GetEventStatsRequest.ValidateAll() if the designated +// constraints aren't met. +type GetEventStatsRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetEventStatsRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetEventStatsRequestMultiError) AllErrors() []error { return m } + +// GetEventStatsRequestValidationError is the validation error returned by +// GetEventStatsRequest.Validate if the designated constraints aren't met. +type GetEventStatsRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetEventStatsRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetEventStatsRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetEventStatsRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetEventStatsRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetEventStatsRequestValidationError) ErrorName() string { + return "GetEventStatsRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetEventStatsRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetEventStatsRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetEventStatsRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetEventStatsRequestValidationError{} + +// Validate checks the field values on GetEventStatsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetEventStatsResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetEventStatsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetEventStatsResponseMultiError, or nil if none found. +func (m *GetEventStatsResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetEventStatsResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for TotalCount + + // no validation rules for StartDate + + // no validation rules for EndDate + + if len(errors) > 0 { + return GetEventStatsResponseMultiError(errors) + } + + return nil +} + +// GetEventStatsResponseMultiError is an error wrapping multiple validation +// errors returned by GetEventStatsResponse.ValidateAll() if the designated +// constraints aren't met. +type GetEventStatsResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetEventStatsResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetEventStatsResponseMultiError) AllErrors() []error { return m } + +// GetEventStatsResponseValidationError is the validation error returned by +// GetEventStatsResponse.Validate if the designated constraints aren't met. +type GetEventStatsResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetEventStatsResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetEventStatsResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetEventStatsResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetEventStatsResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetEventStatsResponseValidationError) ErrorName() string { + return "GetEventStatsResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetEventStatsResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetEventStatsResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetEventStatsResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetEventStatsResponseValidationError{} + +// Validate checks the field values on GetEventStatsByMonthRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetEventStatsByMonthRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetEventStatsByMonthRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetEventStatsByMonthRequestMultiError, or nil if none found. +func (m *GetEventStatsByMonthRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetEventStatsByMonthRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if utf8.RuneCountInString(m.GetStartDate()) < 1 { + err := GetEventStatsByMonthRequestValidationError{ + field: "StartDate", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if utf8.RuneCountInString(m.GetEndDate()) < 1 { + err := GetEventStatsByMonthRequestValidationError{ + field: "EndDate", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetImpact()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetEventStatsByMonthRequestValidationError{ + field: "Impact", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetEventStatsByMonthRequestValidationError{ + field: "Impact", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetImpact()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetEventStatsByMonthRequestValidationError{ + field: "Impact", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Source + + // no validation rules for Service + + // no validation rules for GroupByService + + if len(errors) > 0 { + return GetEventStatsByMonthRequestMultiError(errors) + } + + return nil +} + +// GetEventStatsByMonthRequestMultiError is an error wrapping multiple +// validation errors returned by GetEventStatsByMonthRequest.ValidateAll() if +// the designated constraints aren't met. +type GetEventStatsByMonthRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetEventStatsByMonthRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetEventStatsByMonthRequestMultiError) AllErrors() []error { return m } + +// GetEventStatsByMonthRequestValidationError is the validation error returned +// by GetEventStatsByMonthRequest.Validate if the designated constraints +// aren't met. +type GetEventStatsByMonthRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetEventStatsByMonthRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetEventStatsByMonthRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetEventStatsByMonthRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetEventStatsByMonthRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetEventStatsByMonthRequestValidationError) ErrorName() string { + return "GetEventStatsByMonthRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetEventStatsByMonthRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetEventStatsByMonthRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetEventStatsByMonthRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetEventStatsByMonthRequestValidationError{} + +// Validate checks the field values on MonthlyStats with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *MonthlyStats) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on MonthlyStats with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in MonthlyStatsMultiError, or +// nil if none found. +func (m *MonthlyStats) ValidateAll() error { + return m.validate(true) +} + +func (m *MonthlyStats) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Year + + // no validation rules for Month + + // no validation rules for Count + + // no validation rules for Service + + if len(errors) > 0 { + return MonthlyStatsMultiError(errors) + } + + return nil +} + +// MonthlyStatsMultiError is an error wrapping multiple validation errors +// returned by MonthlyStats.ValidateAll() if the designated constraints aren't met. +type MonthlyStatsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m MonthlyStatsMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m MonthlyStatsMultiError) AllErrors() []error { return m } + +// MonthlyStatsValidationError is the validation error returned by +// MonthlyStats.Validate if the designated constraints aren't met. +type MonthlyStatsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e MonthlyStatsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e MonthlyStatsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e MonthlyStatsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e MonthlyStatsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e MonthlyStatsValidationError) ErrorName() string { return "MonthlyStatsValidationError" } + +// Error satisfies the builtin error interface +func (e MonthlyStatsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sMonthlyStats.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = MonthlyStatsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = MonthlyStatsValidationError{} + +// Validate checks the field values on GetEventStatsByMonthResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetEventStatsByMonthResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetEventStatsByMonthResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetEventStatsByMonthResponseMultiError, or nil if none found. +func (m *GetEventStatsByMonthResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetEventStatsByMonthResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetStats() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetEventStatsByMonthResponseValidationError{ + field: fmt.Sprintf("Stats[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetEventStatsByMonthResponseValidationError{ + field: fmt.Sprintf("Stats[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetEventStatsByMonthResponseValidationError{ + field: fmt.Sprintf("Stats[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + // no validation rules for TotalCount + + // no validation rules for StartDate + + // no validation rules for EndDate + + if len(errors) > 0 { + return GetEventStatsByMonthResponseMultiError(errors) + } + + return nil +} + +// GetEventStatsByMonthResponseMultiError is an error wrapping multiple +// validation errors returned by GetEventStatsByMonthResponse.ValidateAll() if +// the designated constraints aren't met. +type GetEventStatsByMonthResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetEventStatsByMonthResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetEventStatsByMonthResponseMultiError) AllErrors() []error { return m } + +// GetEventStatsByMonthResponseValidationError is the validation error returned +// by GetEventStatsByMonthResponse.Validate if the designated constraints +// aren't met. +type GetEventStatsByMonthResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetEventStatsByMonthResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetEventStatsByMonthResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetEventStatsByMonthResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetEventStatsByMonthResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetEventStatsByMonthResponseValidationError) ErrorName() string { + return "GetEventStatsByMonthResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetEventStatsByMonthResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetEventStatsByMonthResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetEventStatsByMonthResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetEventStatsByMonthResponseValidationError{} diff --git a/generated/proto/event/v1alpha1/event_grpc.pb.go b/generated/proto/event/v1alpha1/event_grpc.pb.go index 4df8037..6ccfe74 100644 --- a/generated/proto/event/v1alpha1/event_grpc.pb.go +++ b/generated/proto/event/v1alpha1/event_grpc.pb.go @@ -19,16 +19,18 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - EventService_CreateEvent_FullMethodName = "/tracker.event.v1alpha1.EventService/CreateEvent" - EventService_UpdateEvent_FullMethodName = "/tracker.event.v1alpha1.EventService/UpdateEvent" - EventService_DeleteEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/DeleteEvents" - EventService_GetEvent_FullMethodName = "/tracker.event.v1alpha1.EventService/GetEvent" - EventService_SearchEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/SearchEvents" - EventService_ListEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/ListEvents" - EventService_TodayEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/TodayEvents" - EventService_AddChangelogEntry_FullMethodName = "/tracker.event.v1alpha1.EventService/AddChangelogEntry" - EventService_GetEventChangelog_FullMethodName = "/tracker.event.v1alpha1.EventService/GetEventChangelog" - EventService_AddSlackId_FullMethodName = "/tracker.event.v1alpha1.EventService/AddSlackId" + EventService_CreateEvent_FullMethodName = "/tracker.event.v1alpha1.EventService/CreateEvent" + EventService_UpdateEvent_FullMethodName = "/tracker.event.v1alpha1.EventService/UpdateEvent" + EventService_DeleteEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/DeleteEvents" + EventService_GetEvent_FullMethodName = "/tracker.event.v1alpha1.EventService/GetEvent" + EventService_SearchEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/SearchEvents" + EventService_ListEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/ListEvents" + EventService_TodayEvents_FullMethodName = "/tracker.event.v1alpha1.EventService/TodayEvents" + EventService_AddChangelogEntry_FullMethodName = "/tracker.event.v1alpha1.EventService/AddChangelogEntry" + EventService_GetEventChangelog_FullMethodName = "/tracker.event.v1alpha1.EventService/GetEventChangelog" + EventService_AddSlackId_FullMethodName = "/tracker.event.v1alpha1.EventService/AddSlackId" + EventService_GetEventStats_FullMethodName = "/tracker.event.v1alpha1.EventService/GetEventStats" + EventService_GetEventStatsByMonth_FullMethodName = "/tracker.event.v1alpha1.EventService/GetEventStatsByMonth" ) // EventServiceClient is the client API for EventService service. @@ -48,6 +50,10 @@ type EventServiceClient interface { GetEventChangelog(ctx context.Context, in *GetEventChangelogRequest, opts ...grpc.CallOption) (*GetEventChangelogResponse, error) // Add a Slack ID to an existing event AddSlackId(ctx context.Context, in *AddSlackIdRequest, opts ...grpc.CallOption) (*AddSlackIdResponse, error) + // Get event statistics count with filters + GetEventStats(ctx context.Context, in *GetEventStatsRequest, opts ...grpc.CallOption) (*GetEventStatsResponse, error) + // Get event statistics aggregated by month + GetEventStatsByMonth(ctx context.Context, in *GetEventStatsByMonthRequest, opts ...grpc.CallOption) (*GetEventStatsByMonthResponse, error) } type eventServiceClient struct { @@ -158,6 +164,26 @@ func (c *eventServiceClient) AddSlackId(ctx context.Context, in *AddSlackIdReque return out, nil } +func (c *eventServiceClient) GetEventStats(ctx context.Context, in *GetEventStatsRequest, opts ...grpc.CallOption) (*GetEventStatsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetEventStatsResponse) + err := c.cc.Invoke(ctx, EventService_GetEventStats_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eventServiceClient) GetEventStatsByMonth(ctx context.Context, in *GetEventStatsByMonthRequest, opts ...grpc.CallOption) (*GetEventStatsByMonthResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetEventStatsByMonthResponse) + err := c.cc.Invoke(ctx, EventService_GetEventStatsByMonth_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // EventServiceServer is the server API for EventService service. // All implementations must embed UnimplementedEventServiceServer // for forward compatibility. @@ -175,6 +201,10 @@ type EventServiceServer interface { GetEventChangelog(context.Context, *GetEventChangelogRequest) (*GetEventChangelogResponse, error) // Add a Slack ID to an existing event AddSlackId(context.Context, *AddSlackIdRequest) (*AddSlackIdResponse, error) + // Get event statistics count with filters + GetEventStats(context.Context, *GetEventStatsRequest) (*GetEventStatsResponse, error) + // Get event statistics aggregated by month + GetEventStatsByMonth(context.Context, *GetEventStatsByMonthRequest) (*GetEventStatsByMonthResponse, error) mustEmbedUnimplementedEventServiceServer() } @@ -215,6 +245,12 @@ func (UnimplementedEventServiceServer) GetEventChangelog(context.Context, *GetEv func (UnimplementedEventServiceServer) AddSlackId(context.Context, *AddSlackIdRequest) (*AddSlackIdResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AddSlackId not implemented") } +func (UnimplementedEventServiceServer) GetEventStats(context.Context, *GetEventStatsRequest) (*GetEventStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetEventStats not implemented") +} +func (UnimplementedEventServiceServer) GetEventStatsByMonth(context.Context, *GetEventStatsByMonthRequest) (*GetEventStatsByMonthResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetEventStatsByMonth not implemented") +} func (UnimplementedEventServiceServer) mustEmbedUnimplementedEventServiceServer() {} func (UnimplementedEventServiceServer) testEmbeddedByValue() {} @@ -416,6 +452,42 @@ func _EventService_AddSlackId_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _EventService_GetEventStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetEventStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EventServiceServer).GetEventStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EventService_GetEventStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EventServiceServer).GetEventStats(ctx, req.(*GetEventStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EventService_GetEventStatsByMonth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetEventStatsByMonthRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EventServiceServer).GetEventStatsByMonth(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EventService_GetEventStatsByMonth_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EventServiceServer).GetEventStatsByMonth(ctx, req.(*GetEventStatsByMonthRequest)) + } + return interceptor(ctx, in, info, handler) +} + // EventService_ServiceDesc is the grpc.ServiceDesc for EventService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -463,6 +535,14 @@ var EventService_ServiceDesc = grpc.ServiceDesc{ MethodName: "AddSlackId", Handler: _EventService_AddSlackId_Handler, }, + { + MethodName: "GetEventStats", + Handler: _EventService_GetEventStats_Handler, + }, + { + MethodName: "GetEventStatsByMonth", + Handler: _EventService_GetEventStatsByMonth_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/event/v1alpha1/event.proto", diff --git a/internal/stores/event.go b/internal/stores/event.go index 4170672..85badab 100644 --- a/internal/stores/event.go +++ b/internal/stores/event.go @@ -99,6 +99,65 @@ func (c *EventStoreClient) Delete(ctx context.Context, filter map[string]interfa return } +// CountWithFilter counts events matching the given filter +func (c *EventStoreClient) CountWithFilter(ctx context.Context, filter bson.D) (int64, error) { + return c.collection.CountDocuments(ctx, filter) +} + +// MonthlyStatsResult represents a single month's statistics +type MonthlyStatsResult struct { + Year int32 `bson:"year"` + Month int32 `bson:"month"` + Service string `bson:"service,omitempty"` + Count int64 `bson:"count"` +} + +// AggregateByMonth aggregates events by month with optional service grouping +func (c *EventStoreClient) AggregateByMonth(ctx context.Context, matchFilter bson.D, groupByService bool) ([]MonthlyStatsResult, error) { + // Build the group stage + groupID := bson.D{ + {Key: "year", Value: bson.D{{Key: "$year", Value: bson.D{{Key: "$toDate", Value: bson.D{{Key: "$multiply", Value: bson.A{"$metadata.createdat.seconds", 1000}}}}}}}}, + {Key: "month", Value: bson.D{{Key: "$month", Value: bson.D{{Key: "$toDate", Value: bson.D{{Key: "$multiply", Value: bson.A{"$metadata.createdat.seconds", 1000}}}}}}}}, + } + + if groupByService { + groupID = append(groupID, bson.E{Key: "service", Value: "$attributes.service"}) + } + + pipeline := mongo.Pipeline{ + {{Key: "$match", Value: matchFilter}}, + {{Key: "$group", Value: bson.D{ + {Key: "_id", Value: groupID}, + {Key: "count", Value: bson.D{{Key: "$sum", Value: 1}}}, + }}}, + {{Key: "$project", Value: bson.D{ + {Key: "_id", Value: 0}, + {Key: "year", Value: "$_id.year"}, + {Key: "month", Value: "$_id.month"}, + {Key: "service", Value: "$_id.service"}, + {Key: "count", Value: 1}, + }}}, + {{Key: "$sort", Value: bson.D{ + {Key: "year", Value: 1}, + {Key: "month", Value: 1}, + {Key: "service", Value: 1}, + }}}, + } + + cursor, err := c.collection.Aggregate(ctx, pipeline) + if err != nil { + return nil, err + } + defer cursor.Close(ctx) + + var results []MonthlyStatsResult + if err = cursor.All(ctx, &results); err != nil { + return nil, err + } + + return results, nil +} + /* // Fonction pour construire dynamiquement bson.D en fonction des champs non vides func buildBsonUpdate(event *v1alpha1.Event) bson.D { diff --git a/internal/utils/utils.go b/internal/utils/utils.go index a8c002c..70454cc 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -7,10 +7,9 @@ import ( "regexp" "time" - "go.mongodb.org/mongo-driver/bson" - v1alpha1 "github.com/bananaops/tracker/generated/proto/event/v1alpha1" "github.com/google/uuid" + "go.mongodb.org/mongo-driver/bson" ) func CreateFilter(e *v1alpha1.SearchEventsRequest) (map[string]interface{}, error) { @@ -133,3 +132,79 @@ func DecodeEscapedChars(encodedStr string) (string, error) { } return decodedStr, nil } + +// StatsFilter represents the filter parameters for event statistics +type StatsFilter struct { + StartDate string + EndDate string + Environments []int32 + Impact *bool + Priorities []int32 + Types []int32 + Statuses []int32 + Source string + Service string +} + +// CreateStatsFilter builds a bson.D filter for event statistics queries +func CreateStatsFilter(f *StatsFilter) (bson.D, error) { + filter := bson.D{} + + // Parse and validate dates (required) + if f.StartDate == "" || f.EndDate == "" { + return nil, errors.New("start_date and end_date are required") + } + + start, err := parseDate(f.StartDate) + if err != nil { + return nil, fmt.Errorf("invalid start_date: %w", err) + } + end, err := parseDate(f.EndDate) + if err != nil { + return nil, fmt.Errorf("invalid end_date: %w", err) + } + + if err = checkDateInverted(start, end); err != nil { + return nil, err + } + + // Filter by created_at timestamp + filter = append(filter, bson.E{ + Key: "metadata.createdat.seconds", + Value: bson.D{ + {Key: "$gte", Value: start.Unix()}, + {Key: "$lte", Value: end.Unix()}, + }, + }) + + // Optional filters + if len(f.Environments) > 0 { + filter = append(filter, bson.E{Key: "attributes.environment", Value: bson.D{{Key: "$in", Value: f.Environments}}}) + } + + if f.Impact != nil { + filter = append(filter, bson.E{Key: "attributes.impact", Value: *f.Impact}) + } + + if len(f.Priorities) > 0 { + filter = append(filter, bson.E{Key: "attributes.priority", Value: bson.D{{Key: "$in", Value: f.Priorities}}}) + } + + if len(f.Types) > 0 { + filter = append(filter, bson.E{Key: "attributes.type", Value: bson.D{{Key: "$in", Value: f.Types}}}) + } + + if len(f.Statuses) > 0 { + filter = append(filter, bson.E{Key: "attributes.status", Value: bson.D{{Key: "$in", Value: f.Statuses}}}) + } + + if f.Source != "" { + filter = append(filter, bson.E{Key: "attributes.source", Value: f.Source}) + } + + if f.Service != "" { + filter = append(filter, bson.E{Key: "attributes.service", Value: f.Service}) + } + + return filter, nil +} diff --git a/internal/utils/utils_test.go b/internal/utils/utils_test.go index b1945e1..96a3036 100644 --- a/internal/utils/utils_test.go +++ b/internal/utils/utils_test.go @@ -161,3 +161,162 @@ func TestCatchPullRequestIdError(t *testing.T) { assert.Error(t, e) } } + + +func TestCreateStatsFilter(t *testing.T) { + testCases := []struct { + name string + filter *StatsFilter + expectError bool + expectedFields int // Number of expected fields in the filter + }{ + { + name: "OK - Only required dates", + filter: &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + }, + expectError: false, + expectedFields: 1, // Only date filter + }, + { + name: "OK - With environments filter", + filter: &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + Environments: []int32{7}, // production + }, + expectError: false, + expectedFields: 2, + }, + { + name: "OK - With all filters", + filter: &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + Environments: []int32{7}, + Priorities: []int32{1, 2}, + Types: []int32{1}, + Statuses: []int32{3}, + Source: "slack", + Service: "auth-service", + }, + expectError: false, + expectedFields: 7, + }, + { + name: "OK - With impact filter true", + filter: &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + Impact: boolPtr(true), + }, + expectError: false, + expectedFields: 2, + }, + { + name: "OK - With impact filter false", + filter: &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + Impact: boolPtr(false), + }, + expectError: false, + expectedFields: 2, + }, + { + name: "ERROR - Missing start_date", + filter: &StatsFilter{ + EndDate: "2025-12-31", + }, + expectError: true, + }, + { + name: "ERROR - Missing end_date", + filter: &StatsFilter{ + StartDate: "2025-01-01", + }, + expectError: true, + }, + { + name: "ERROR - Missing both dates", + filter: &StatsFilter{ + Environments: []int32{7}, + }, + expectError: true, + }, + { + name: "ERROR - Invalid start_date format", + filter: &StatsFilter{ + StartDate: "invalid-date", + EndDate: "2025-12-31", + }, + expectError: true, + }, + { + name: "ERROR - Invalid end_date format", + filter: &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "invalid-date", + }, + expectError: true, + }, + { + name: "ERROR - Inverted dates", + filter: &StatsFilter{ + StartDate: "2025-12-31", + EndDate: "2025-01-01", + }, + expectError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := CreateStatsFilter(tc.filter) + + if tc.expectError { + assert.Error(t, err) + assert.Nil(t, result) + } else { + assert.NoError(t, err) + assert.NotNil(t, result) + assert.Len(t, result, tc.expectedFields) + } + }) + } +} + +func TestCreateStatsFilterDateRange(t *testing.T) { + filter := &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + } + + result, err := CreateStatsFilter(filter) + assert.NoError(t, err) + assert.NotNil(t, result) + + // Verify the date filter is correctly set + // The filter should contain metadata.createdat.seconds with $gte and $lte + assert.Len(t, result, 1) + assert.Equal(t, "metadata.createdat.seconds", result[0].Key) +} + +func TestCreateStatsFilterMultipleEnvironments(t *testing.T) { + filter := &StatsFilter{ + StartDate: "2025-01-01", + EndDate: "2025-12-31", + Environments: []int32{6, 7}, // preproduction and production + } + + result, err := CreateStatsFilter(filter) + assert.NoError(t, err) + assert.NotNil(t, result) + assert.Len(t, result, 2) +} + +// Helper function to create bool pointer +func boolPtr(b bool) *bool { + return &b +} diff --git a/proto/event/v1alpha1/event.proto b/proto/event/v1alpha1/event.proto index 8837c10..360815c 100644 --- a/proto/event/v1alpha1/event.proto +++ b/proto/event/v1alpha1/event.proto @@ -59,6 +59,16 @@ service EventService { body: "*" }; } + + // Get event statistics count with filters + rpc GetEventStats(GetEventStatsRequest) returns (GetEventStatsResponse) { + option (google.api.http) = {get: "/api/v1alpha1/events/stats"}; + } + + // Get event statistics aggregated by month + rpc GetEventStatsByMonth(GetEventStatsByMonthRequest) returns (GetEventStatsByMonthResponse) { + option (google.api.http) = {get: "/api/v1alpha1/events/stats/monthly"}; + } } message EventAttributes { @@ -286,3 +296,60 @@ enum ChangeType { locked = 8; unlocked = 9; } + +// Request for event statistics count +message GetEventStatsRequest { + // Required: start date for the period (format: 2006-01-02 or ISO8601) + string start_date = 1 [(validate.rules).string.min_len = 1]; + // Required: end date for the period (format: 2006-01-02 or ISO8601) + string end_date = 2 [(validate.rules).string.min_len = 1]; + // Optional filters + repeated Environment environments = 3; + google.protobuf.BoolValue impact = 4; + repeated Priority priorities = 5; + repeated Type types = 6; + repeated Status statuses = 7; + string source = 8; + string service = 9; +} + +// Response for event statistics count +message GetEventStatsResponse { + uint64 total_count = 1; + string start_date = 2; + string end_date = 3; +} + +// Request for event statistics by month +message GetEventStatsByMonthRequest { + // Required: start date for the period (format: 2006-01-02 or ISO8601) + string start_date = 1 [(validate.rules).string.min_len = 1]; + // Required: end date for the period (format: 2006-01-02 or ISO8601) + string end_date = 2 [(validate.rules).string.min_len = 1]; + // Optional filters + repeated Environment environments = 3; + google.protobuf.BoolValue impact = 4; + repeated Priority priorities = 5; + repeated Type types = 6; + repeated Status statuses = 7; + string source = 8; + string service = 9; + // Group by service in addition to month + bool group_by_service = 10; +} + +// Monthly statistics entry +message MonthlyStats { + int32 year = 1; + int32 month = 2; + uint64 count = 3; + string service = 4; // Only populated if group_by_service is true +} + +// Response for event statistics by month +message GetEventStatsByMonthResponse { + repeated MonthlyStats stats = 1; + uint64 total_count = 2; + string start_date = 3; + string end_date = 4; +} diff --git a/server/event.go b/server/event.go index 006578b..e17ed18 100644 --- a/server/event.go +++ b/server/event.go @@ -717,6 +717,181 @@ func recordEvent(status string, service string, environment string, duration tim eventDuration.With(prometheus.Labels{"status": status, "service": service, "environment": environment}).Observe(duration.Seconds()) } +func (e *Event) GetEventStats( + ctx context.Context, + i *v1alpha1.GetEventStatsRequest, +) (*v1alpha1.GetEventStatsResponse, error) { + + // Build filter from request + statsFilter := &utils.StatsFilter{ + StartDate: i.StartDate, + EndDate: i.EndDate, + Source: i.Source, + Service: i.Service, + } + + // Convert environments + if len(i.Environments) > 0 { + statsFilter.Environments = make([]int32, len(i.Environments)) + for idx, env := range i.Environments { + statsFilter.Environments[idx] = int32(env) + } + } + + // Convert impact + if i.Impact != nil { + impact := i.Impact.Value + statsFilter.Impact = &impact + } + + // Convert priorities + if len(i.Priorities) > 0 { + statsFilter.Priorities = make([]int32, len(i.Priorities)) + for idx, p := range i.Priorities { + statsFilter.Priorities[idx] = int32(p) + } + } + + // Convert types + if len(i.Types) > 0 { + statsFilter.Types = make([]int32, len(i.Types)) + for idx, t := range i.Types { + statsFilter.Types[idx] = int32(t) + } + } + + // Convert statuses + if len(i.Statuses) > 0 { + statsFilter.Statuses = make([]int32, len(i.Statuses)) + for idx, s := range i.Statuses { + statsFilter.Statuses[idx] = int32(s) + } + } + + filter, err := utils.CreateStatsFilter(statsFilter) + if err != nil { + return nil, fmt.Errorf("failed to create stats filter: %w", err) + } + + count, err := e.store.CountWithFilter(ctx, filter) + if err != nil { + return nil, fmt.Errorf("failed to count events: %w", err) + } + + // Safe conversion: count is always >= 0 + var totalCount uint64 + if count >= 0 { + totalCount = uint64(count) // #nosec G115 + } + + e.logger.Info("event stats retrieved", + "start_date", i.StartDate, + "end_date", i.EndDate, + "count", totalCount, + ) + + return &v1alpha1.GetEventStatsResponse{ + TotalCount: totalCount, + StartDate: i.StartDate, + EndDate: i.EndDate, + }, nil +} + +func (e *Event) GetEventStatsByMonth( + ctx context.Context, + i *v1alpha1.GetEventStatsByMonthRequest, +) (*v1alpha1.GetEventStatsByMonthResponse, error) { + + // Build filter from request + statsFilter := &utils.StatsFilter{ + StartDate: i.StartDate, + EndDate: i.EndDate, + Source: i.Source, + Service: i.Service, + } + + // Convert environments + if len(i.Environments) > 0 { + statsFilter.Environments = make([]int32, len(i.Environments)) + for idx, env := range i.Environments { + statsFilter.Environments[idx] = int32(env) + } + } + + // Convert impact + if i.Impact != nil { + impact := i.Impact.Value + statsFilter.Impact = &impact + } + + // Convert priorities + if len(i.Priorities) > 0 { + statsFilter.Priorities = make([]int32, len(i.Priorities)) + for idx, p := range i.Priorities { + statsFilter.Priorities[idx] = int32(p) + } + } + + // Convert types + if len(i.Types) > 0 { + statsFilter.Types = make([]int32, len(i.Types)) + for idx, t := range i.Types { + statsFilter.Types[idx] = int32(t) + } + } + + // Convert statuses + if len(i.Statuses) > 0 { + statsFilter.Statuses = make([]int32, len(i.Statuses)) + for idx, s := range i.Statuses { + statsFilter.Statuses[idx] = int32(s) + } + } + + filter, err := utils.CreateStatsFilter(statsFilter) + if err != nil { + return nil, fmt.Errorf("failed to create stats filter: %w", err) + } + + results, err := e.store.AggregateByMonth(ctx, filter, i.GroupByService) + if err != nil { + return nil, fmt.Errorf("failed to aggregate events by month: %w", err) + } + + // Convert results to proto + stats := make([]*v1alpha1.MonthlyStats, len(results)) + var totalCount uint64 + for idx, r := range results { + // Safe conversion: r.Count is always >= 0 + var count uint64 + if r.Count >= 0 { + count = uint64(r.Count) // #nosec G115 + } + stats[idx] = &v1alpha1.MonthlyStats{ + Year: r.Year, + Month: r.Month, + Count: count, + Service: r.Service, + } + totalCount += count + } + + e.logger.Info("event stats by month retrieved", + "start_date", i.StartDate, + "end_date", i.EndDate, + "months_count", len(stats), + "total_count", totalCount, + "group_by_service", i.GroupByService, + ) + + return &v1alpha1.GetEventStatsByMonthResponse{ + Stats: stats, + TotalCount: totalCount, + StartDate: i.StartDate, + EndDate: i.EndDate, + }, nil +} + func init() { // Enregistrer les métriques prometheus.MustRegister(eventCounter) diff --git a/server/tracker.code-workspace b/server/tracker.code-workspace new file mode 100644 index 0000000..bf353a5 --- /dev/null +++ b/server/tracker.code-workspace @@ -0,0 +1,32 @@ +{ + "folders": [ + { + "path": ".." + }, + { + "path": "../../tracker-slack" + } + ], + "settings": { + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#a258f7", + "activityBar.background": "#a258f7", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#f8aa67", + "activityBarBadge.foreground": "#15202b", + "commandCenter.border": "#e7e7e799", + "sash.hoverBorder": "#a258f7", + "statusBar.background": "#8727f5", + "statusBar.foreground": "#e7e7e7", + "statusBarItem.hoverBackground": "#a258f7", + "statusBarItem.remoteBackground": "#8727f5", + "statusBarItem.remoteForeground": "#e7e7e7", + "titleBar.activeBackground": "#8727f5", + "titleBar.activeForeground": "#e7e7e7", + "titleBar.inactiveBackground": "#8727f599", + "titleBar.inactiveForeground": "#e7e7e799" + }, + "peacock.color": "#8727F5" + } +}