diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index 9a0d69e352..e1b977b113 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -817,7 +817,6 @@ "type": "string", "enum": [ "string", - "barcodeqr", "longform", "options", "number", @@ -829,7 +828,8 @@ "formula", "auto", "json", - "internal" + "internal", + "barcodeqr" ], "description": "Defines the type of the column, most explain themselves, a link column is a relationship." }, @@ -1021,7 +1021,6 @@ "type": "string", "enum": [ "string", - "barcodeqr", "longform", "options", "number", @@ -1033,7 +1032,8 @@ "formula", "auto", "json", - "internal" + "internal", + "barcodeqr" ], "description": "Defines the type of the column, most explain themselves, a link column is a relationship." }, @@ -1236,7 +1236,6 @@ "type": "string", "enum": [ "string", - "barcodeqr", "longform", "options", "number", @@ -1248,7 +1247,8 @@ "formula", "auto", "json", - "internal" + "internal", + "barcodeqr" ], "description": "Defines the type of the column, most explain themselves, a link column is a relationship." }, @@ -2054,6 +2054,24 @@ } } }, + "/metrics": { + "get": { + "operationId": "getById", + "summary": "Retrieve Budibase tenant metrics", + "description": "Output metrics in OpenMetrics format compatible with Prometheus", + "tags": [ + "metrics" + ], + "responses": { + "200": { + "description": "Returns tenant metrics.", + "content": { + "text/plain": null + } + } + } + } + }, "/queries/{queryId}": { "post": { "operationId": "execute", diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 69e44d881c..dc92c818b7 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -603,7 +603,6 @@ components: type: string enum: - string - - barcodeqr - longform - options - number @@ -616,6 +615,7 @@ components: - auto - json - internal + - barcodeqr description: Defines the type of the column, most explain themselves, a link column is a relationship. constraints: @@ -766,7 +766,6 @@ components: type: string enum: - string - - barcodeqr - longform - options - number @@ -779,6 +778,7 @@ components: - auto - json - internal + - barcodeqr description: Defines the type of the column, most explain themselves, a link column is a relationship. constraints: @@ -936,7 +936,6 @@ components: type: string enum: - string - - barcodeqr - longform - options - number @@ -949,6 +948,7 @@ components: - auto - json - internal + - barcodeqr description: Defines the type of the column, most explain themselves, a link column is a relationship. constraints: @@ -1531,6 +1531,18 @@ paths: examples: applications: $ref: "#/components/examples/applications" + /metrics: + get: + operationId: getById + summary: Retrieve Budibase tenant metrics + description: Output metrics in OpenMetrics format compatible with Prometheus + tags: + - metrics + responses: + "200": + description: Returns tenant metrics. + content: + ? text/plain "/queries/{queryId}": post: operationId: execute diff --git a/packages/server/src/api/controllers/public/metrics.ts b/packages/server/src/api/controllers/public/metrics.ts index 65f8849f7f..be78b86fc4 100644 --- a/packages/server/src/api/controllers/public/metrics.ts +++ b/packages/server/src/api/controllers/public/metrics.ts @@ -13,8 +13,8 @@ export async function fetch(ctx: BBContext) { // *** APPS *** const allDatabases = await dbCore.getAllDbs() - const devAppIDs = await dbCore.getDevAppIDs({ idsOnly: true }) - const prodAppIDs = await dbCore.getProdAppIDs({ idsOnly: true }) + const devAppIDs = await dbCore.getDevAppIDs() + const prodAppIDs = await dbCore.getProdAppIDs() const allAppIds = await dbCore.getAllApps({ idsOnly: true }) // *** USERS *** @@ -147,7 +147,7 @@ export async function fetch(ctx: BBContext) { "budibase_quota_limit_apps", "The limit on the number of apps that can be created", "gauge", - appsQuotaLimit == -1 ? 3000000 : appsQuotaLimit + appsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : appsQuotaLimit ) // **** budibase_quota_usage_rows **** @@ -163,7 +163,7 @@ export async function fetch(ctx: BBContext) { "budibase_quota_limit_rows", "The limit on the number of rows that can be created", "gauge", - rowsQuotaLimit == -1 ? 3000000 : rowsQuotaLimit + rowsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : rowsQuotaLimit ) // **** budibase_quota_usage_plugins **** @@ -179,7 +179,7 @@ export async function fetch(ctx: BBContext) { "budibase_quota_limit_plugins", "The limit on the number of plugins that can be created", "gauge", - pluginsQuotaLimit == -1 ? 3000000 : pluginsQuotaLimit + pluginsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : pluginsQuotaLimit ) // **** budibase_quota_usage_user_groups **** @@ -195,7 +195,7 @@ export async function fetch(ctx: BBContext) { "budibase_quota_limit_user_groups", "The limit on the number of user groups that can be created", "gauge", - userGroupsQuotaLimit == -1 ? 3000000 : userGroupsQuotaLimit + userGroupsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : userGroupsQuotaLimit ) // **** budibase_quota_usage_queries **** @@ -211,7 +211,7 @@ export async function fetch(ctx: BBContext) { "budibase_quota_limit_queries", "The limit on the number of queries for the current month", "gauge", - queryQuotaLimit == -1 ? 3000000 : queryQuotaLimit + queryQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : queryQuotaLimit ) // **** budibase_quota_usage_automations **** @@ -227,10 +227,12 @@ export async function fetch(ctx: BBContext) { "budibase_quota_limit_automations", "The limit on the number of automations that can be created", "gauge", - automationsQuotaLimit == -1 ? 3000000 : automationsQuotaLimit + automationsQuotaLimit == -1 + ? Number.MAX_SAFE_INTEGER + : automationsQuotaLimit ) - ctx.body = outputString + ctx.set('Content-Type', 'text/plain'); } export function convertToOpenMetrics( diff --git a/packages/server/src/api/routes/public/index.ts b/packages/server/src/api/routes/public/index.ts index e67c10fe02..e2bce1e730 100644 --- a/packages/server/src/api/routes/public/index.ts +++ b/packages/server/src/api/routes/public/index.ts @@ -13,7 +13,7 @@ import env from "../../../environment" // below imports don't have declaration files const Router = require("@koa/router") const { RateLimit, Stores } = require("koa2-ratelimit") -import { redis, permissions } from "@budibase/backend-core" +import { middleware, redis, permissions } from "@budibase/backend-core" const { PermissionType, PermissionLevel } = permissions const PREFIX = "/api/public/v1" @@ -92,6 +92,13 @@ function addToRouter(endpoints: any) { } } +function applyAdminRoutes(endpoints: any) { + addMiddleware(endpoints.read, middleware.builderOrAdmin) + addMiddleware(endpoints.write, middleware.builderOrAdmin) + addToRouter(endpoints.read) + addToRouter(endpoints.write) +} + function applyRoutes( endpoints: any, permType: string, @@ -120,8 +127,8 @@ function applyRoutes( addToRouter(endpoints.write) } +applyAdminRoutes(metricEndpoints) applyRoutes(appEndpoints, PermissionType.APP, "appId") -applyRoutes(metricEndpoints, PermissionType.APP, "appId") applyRoutes(tableEndpoints, PermissionType.TABLE, "tableId") applyRoutes(userEndpoints, PermissionType.USER, "userId") applyRoutes(queryEndpoints, PermissionType.QUERY, "queryId") diff --git a/packages/server/src/api/routes/tests/metrics.spec.js b/packages/server/src/api/routes/tests/metrics.spec.js new file mode 100644 index 0000000000..6e689f040a --- /dev/null +++ b/packages/server/src/api/routes/tests/metrics.spec.js @@ -0,0 +1,49 @@ +const { roles, utils } = require("@budibase/backend-core") +const { checkBuilderEndpoint } = require("./utilities/TestFunctions") +const setup = require("./utilities") +const { BUILTIN_ROLE_IDS } = roles + +jest.setTimeout(30000) + +// jest.mock("../../../utilities/workerRequests", () => ({ +// getGlobalUsers: jest.fn(() => { +// return {} +// }), +// getGlobalSelf: jest.fn(() => { +// return {} +// }), +// deleteGlobalUser: jest.fn(), +// })) + +describe("/metrics", () => { + let request = setup.getRequest() + let config = setup.getConfig() + + afterAll(setup.afterAll) + + // For some reason this cannot be a beforeAll or the test "should be able to update the user" fail + beforeEach(async () => { + await config.init() + }) + + describe("get", () => { + it("returns a list of metrics", async () => { + const res = await request + .get(`/api/public/v1/metrics`) + .set(config.defaultHeaders()) + .expect("Content-Type", /text\/plain/) + .expect(200) + expect(res.text).toContain("budibase_tenant_user_count") + }) + + it("should apply authorization to endpoint", async () => { + // await config.createUser() + const res = await request + .get(`/api/public/v1/metrics`) + .set(config.publicHeaders()) + .expect(403) + + }) + }) + +})