Skip to content

Commit

Permalink
add metric endpoint to public API (#72, #80)
Browse files Browse the repository at this point in the history
  • Loading branch information
h44z committed Jan 11, 2025
1 parent 63d85d8 commit 2d78fe3
Show file tree
Hide file tree
Showing 7 changed files with 863 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cmd/wg-portal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,20 @@ func main() {
apiV1BackendPeers := backendV1.NewPeerService(cfg, wireGuardManager, userManager)
apiV1BackendInterfaces := backendV1.NewInterfaceService(cfg, wireGuardManager)
apiV1BackendProvisioning := backendV1.NewProvisioningService(cfg, userManager, wireGuardManager, cfgFileManager)
apiV1BackendMetrics := backendV1.NewMetricsService(cfg, database, userManager, wireGuardManager)
apiV1EndpointUsers := handlersV1.NewUserEndpoint(apiV1BackendUsers)
apiV1EndpointPeers := handlersV1.NewPeerEndpoint(apiV1BackendPeers)
apiV1EndpointInterfaces := handlersV1.NewInterfaceEndpoint(apiV1BackendInterfaces)
apiV1EndpointProvisioning := handlersV1.NewProvisioningEndpoint(apiV1BackendProvisioning)
apiV1EndpointMetrics := handlersV1.NewMetricsEndpoint(apiV1BackendMetrics)

apiV1 := handlersV1.NewRestApi(
userManager,
apiV1EndpointUsers,
apiV1EndpointPeers,
apiV1EndpointInterfaces,
apiV1EndpointProvisioning,
apiV1EndpointMetrics,
)

webSrv, err := core.NewServer(cfg, apiFrontend, apiV1)
Expand Down
24 changes: 24 additions & 0 deletions internal/adapters/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,30 @@ func (r *SqlRepo) GetAllInterfaces(ctx context.Context) ([]domain.Interface, err
return interfaces, nil
}

func (r *SqlRepo) GetInterfaceStats(ctx context.Context, id domain.InterfaceIdentifier) (
*domain.InterfaceStatus,
error,
) {
if id == "" {
return nil, nil
}

var stats []domain.InterfaceStatus

err := r.db.WithContext(ctx).Where("identifier = ?", id).Find(&stats).Error
if err != nil {
return nil, err
}

if len(stats) == 0 {
return nil, domain.ErrNotFound
}

stat := stats[0]

return &stat, nil
}

func (r *SqlRepo) FindInterfaces(ctx context.Context, search string) ([]domain.Interface, error) {
var users []domain.Interface

Expand Down
271 changes: 271 additions & 0 deletions internal/app/api/core/assets/doc/v1_swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,180 @@
}
}
},
"/metrics/by-interface/{id}": {
"get": {
"security": [
{
"BasicAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"Metrics"
],
"summary": "Get all metrics for a WireGuard Portal interface.",
"operationId": "metrics_handleMetricsForInterfaceGet",
"parameters": [
{
"type": "string",
"description": "The WireGuard interface identifier.",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.InterfaceMetrics"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/models.Error"
}
}
}
}
},
"/metrics/by-peer/{id}": {
"get": {
"security": [
{
"BasicAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"Metrics"
],
"summary": "Get all metrics for a WireGuard Portal peer.",
"operationId": "metrics_handleMetricsForPeerGet",
"parameters": [
{
"type": "string",
"description": "The peer identifier (public key).",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.PeerMetrics"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/models.Error"
}
}
}
}
},
"/metrics/by-user/{id}": {
"get": {
"security": [
{
"BasicAuth": []
}
],
"produces": [
"application/json"
],
"tags": [
"Metrics"
],
"summary": "Get all metrics for a WireGuard Portal user.",
"operationId": "metrics_handleMetricsForUserGet",
"parameters": [
{
"type": "string",
"description": "The user identifier.",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.UserMetrics"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/models.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/models.Error"
}
}
}
}
},
"/peer/by-id/{id}": {
"get": {
"security": [
Expand Down Expand Up @@ -1523,6 +1697,26 @@
}
}
},
"models.InterfaceMetrics": {
"type": "object",
"properties": {
"BytesReceived": {
"description": "The number of bytes received by the interface.",
"type": "integer",
"example": 123456789
},
"BytesTransmitted": {
"description": "The number of bytes transmitted by the interface.",
"type": "integer",
"example": 123456789
},
"InterfaceIdentifier": {
"description": "The unique identifier of the interface.",
"type": "string",
"example": "wg0"
}
}
},
"models.Peer": {
"type": "object",
"required": [
Expand Down Expand Up @@ -1728,6 +1922,51 @@
}
}
},
"models.PeerMetrics": {
"type": "object",
"properties": {
"BytesReceived": {
"description": "The number of bytes received by the peer.",
"type": "integer",
"example": 123456789
},
"BytesTransmitted": {
"description": "The number of bytes transmitted by the peer.",
"type": "integer",
"example": 123456789
},
"Endpoint": {
"description": "The current endpoint address of the peer.",
"type": "string",
"example": "12.34.56.78"
},
"IsPingable": {
"description": "If this field is set, the peer is pingable.",
"type": "boolean",
"example": true
},
"LastHandshake": {
"description": "The last time the peer initiated a handshake.",
"type": "string",
"example": "2021-01-01T12:00:00Z"
},
"LastPing": {
"description": "The last time the peer responded to a ICMP ping request.",
"type": "string",
"example": "2021-01-01T12:00:00Z"
},
"LastSessionStart": {
"description": "The last time the peer initiated a session.",
"type": "string",
"example": "2021-01-01T12:00:00Z"
},
"PeerIdentifier": {
"description": "The unique identifier of the peer.",
"type": "string",
"example": "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg="
}
}
},
"models.ProvisioningRequest": {
"type": "object",
"required": [
Expand Down Expand Up @@ -1922,6 +2161,38 @@
"example": true
}
}
},
"models.UserMetrics": {
"type": "object",
"properties": {
"BytesReceived": {
"description": "The total number of bytes received by the user. This is the sum of all bytes received by the peers linked to the user.",
"type": "integer",
"example": 123456789
},
"BytesTransmitted": {
"description": "The total number of bytes transmitted by the user. This is the sum of all bytes transmitted by the peers linked to the user.",
"type": "integer",
"example": 123456789
},
"PeerCount": {
"description": "PeerCount represents the number of peers linked to the user.",
"type": "integer",
"example": 2
},
"PeerMetrics": {
"description": "PeerMetrics represents the metrics of the peers linked to the user.",
"type": "array",
"items": {
"$ref": "#/definitions/models.PeerMetrics"
}
},
"UserIdentifier": {
"description": "The unique identifier of the user.",
"type": "string",
"example": "uid-1234567"
}
}
}
},
"securityDefinitions": {
Expand Down
Loading

0 comments on commit 2d78fe3

Please sign in to comment.