1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-14 01:16:17 +02:00

docs: Metrics tag openapi docs (#3572)

I've copied most of the descriptions from what we did for batch metrics
under the Edge tag, however there are a couple of top level descriptions
that are "fine" but I'm definitely open to suggestions.

---------

Co-authored-by: Thomas Heartman <thomas@getunleash.ai>
This commit is contained in:
Christopher Kolstad 2023-04-26 12:10:57 +02:00 committed by GitHub
parent 3bb09c5ce4
commit 1b248a03e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 693 additions and 48 deletions

View File

@ -6,7 +6,7 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: build (14.x) # temporary solution to trick branch protection rules name: build (18.x) # temporary solution to trick branch protection rules
services: services:
# Label used to access the service container # Label used to access the service container

View File

@ -148,6 +148,7 @@ import { bulkMetricsSchema } from './spec/bulk-metrics-schema';
import { clientMetricsEnvSchema } from './spec/client-metrics-env-schema'; import { clientMetricsEnvSchema } from './spec/client-metrics-env-schema';
import { updateTagsSchema } from './spec/update-tags-schema'; import { updateTagsSchema } from './spec/update-tags-schema';
import { batchStaleSchema } from './spec/batch-stale-schema'; import { batchStaleSchema } from './spec/batch-stale-schema';
import { createApplicationSchema } from './spec/create-application-schema';
// Schemas must have an $id property on the form "#/components/schemas/mySchema". // Schemas must have an $id property on the form "#/components/schemas/mySchema".
export type SchemaId = typeof schemas[keyof typeof schemas]['$id']; export type SchemaId = typeof schemas[keyof typeof schemas]['$id'];
@ -205,6 +206,7 @@ export const schemas: UnleashSchemas = {
contextFieldSchema, contextFieldSchema,
contextFieldsSchema, contextFieldsSchema,
createApiTokenSchema, createApiTokenSchema,
createApplicationSchema,
createFeatureSchema, createFeatureSchema,
createFeatureStrategySchema, createFeatureStrategySchema,
createInvitedUserSchema, createInvitedUserSchema,

View File

@ -81,8 +81,6 @@ const metaRules: Rule[] = [
knownExceptions: [ knownExceptions: [
'apiTokenSchema', 'apiTokenSchema',
'apiTokensSchema', 'apiTokensSchema',
'applicationSchema',
'applicationsSchema',
'batchFeaturesSchema', 'batchFeaturesSchema',
'batchStaleSchema', 'batchStaleSchema',
'changePasswordSchema', 'changePasswordSchema',
@ -90,8 +88,6 @@ const metaRules: Rule[] = [
'clientFeatureSchema', 'clientFeatureSchema',
'clientFeaturesQuerySchema', 'clientFeaturesQuerySchema',
'clientFeaturesSchema', 'clientFeaturesSchema',
'clientMetricsSchema',
'bulkMetricsSchema',
'cloneFeatureSchema', 'cloneFeatureSchema',
'contextFieldSchema', 'contextFieldSchema',
'createApiTokenSchema', 'createApiTokenSchema',
@ -105,17 +101,14 @@ const metaRules: Rule[] = [
'eventsSchema', 'eventsSchema',
'exportResultSchema', 'exportResultSchema',
'exportQuerySchema', 'exportQuerySchema',
'featureEnvironmentMetricsSchema',
'featureEnvironmentSchema', 'featureEnvironmentSchema',
'featureEventsSchema', 'featureEventsSchema',
'featureMetricsSchema',
'featureSchema', 'featureSchema',
'featuresSchema', 'featuresSchema',
'featureStrategySchema', 'featureStrategySchema',
'featureStrategySegmentSchema', 'featureStrategySegmentSchema',
'featureTypeSchema', 'featureTypeSchema',
'featureTypesSchema', 'featureTypesSchema',
'featureUsageSchema',
'featureVariantsSchema', 'featureVariantsSchema',
'feedbackSchema', 'feedbackSchema',
'groupSchema', 'groupSchema',
@ -206,7 +199,6 @@ const metaRules: Rule[] = [
'clientFeatureSchema', 'clientFeatureSchema',
'clientFeaturesQuerySchema', 'clientFeaturesQuerySchema',
'clientFeaturesSchema', 'clientFeaturesSchema',
'clientMetricsSchema',
'cloneFeatureSchema', 'cloneFeatureSchema',
'contextFieldSchema', 'contextFieldSchema',
'contextFieldsSchema', 'contextFieldsSchema',
@ -222,15 +214,12 @@ const metaRules: Rule[] = [
'eventsSchema', 'eventsSchema',
'exportResultSchema', 'exportResultSchema',
'exportQuerySchema', 'exportQuerySchema',
'featureEnvironmentMetricsSchema',
'featureEventsSchema', 'featureEventsSchema',
'featureMetricsSchema',
'featureSchema', 'featureSchema',
'featuresSchema', 'featuresSchema',
'featureStrategySegmentSchema', 'featureStrategySegmentSchema',
'featureTypeSchema', 'featureTypeSchema',
'featureTypesSchema', 'featureTypesSchema',
'featureUsageSchema',
'featureVariantsSchema', 'featureVariantsSchema',
'feedbackSchema', 'feedbackSchema',
'groupSchema', 'groupSchema',

View File

@ -7,31 +7,46 @@ export const applicationSchema = {
required: ['appName'], required: ['appName'],
properties: { properties: {
appName: { appName: {
description: 'Name of the application',
type: 'string', type: 'string',
example: 'accounting',
}, },
sdkVersion: { sdkVersion: {
description:
'Which SDK and version the application reporting uses. Typically represented as `<identifier>:<version>`',
type: 'string', type: 'string',
example: 'unleash-client-java:8.0.0',
}, },
strategies: { strategies: {
description:
'Which [strategies](https://docs.getunleash.io/topics/the-anatomy-of-unleash#activation-strategies) the application has loaded. Useful when trying to figure out if your [custom strategy](https://docs.getunleash.io/reference/custom-activation-strategies) has been loaded in the SDK',
type: 'array', type: 'array',
items: { items: {
type: 'string', type: 'string',
}, },
example: ['standard', 'gradualRollout', 'mySpecialCustomStrategy'],
}, },
description: { description: {
description:
'Extra information added about the application reporting the metrics. Only present if added via the Unleash Admin interface',
type: 'string', type: 'string',
example: 'Application for reporting page visits',
}, },
url: { url: {
description:
'A link to reference the application reporting the metrics. Could for instance be a GitHub link to the repository of the application',
type: 'string', type: 'string',
example: 'https://github.com/Unleash/unleash-client-proxy-js',
}, },
color: { color: {
description: `The CSS color that is used to color the application's entry in the application list`,
type: 'string', type: 'string',
example: 'red',
}, },
icon: { icon: {
description: `An URL to an icon file to be used for the applications's entry in the application list`,
type: 'string', type: 'string',
}, example: 'https://github.com/favicon.ico',
announced: {
type: 'boolean',
}, },
}, },
components: {}, components: {},

View File

@ -3,9 +3,12 @@ import { FromSchema } from 'json-schema-to-ts';
export const applicationsSchema = { export const applicationsSchema = {
$id: '#/components/schemas/applicationsSchema', $id: '#/components/schemas/applicationsSchema',
additionalProperties: false,
type: 'object', type: 'object',
properties: { properties: {
applications: { applications: {
description:
'Contains a list of applications that have connected via an SDK',
type: 'array', type: 'array',
items: { items: {
$ref: '#/components/schemas/applicationSchema', $ref: '#/components/schemas/applicationSchema',

View File

@ -11,12 +11,15 @@ export const bulkMetricsSchema = {
'A batch of metrics accumulated by Edge (or other compatible applications). Includes both application registrations as well usage metrics from clients', 'A batch of metrics accumulated by Edge (or other compatible applications). Includes both application registrations as well usage metrics from clients',
properties: { properties: {
applications: { applications: {
description: 'A list of applications registered by an Unleash SDK',
type: 'array', type: 'array',
items: { items: {
$ref: '#/components/schemas/bulkRegistrationSchema', $ref: '#/components/schemas/bulkRegistrationSchema',
}, },
}, },
metrics: { metrics: {
description:
'a list of client usage metrics registered by downstream providers. (Typically Unleash Edge)',
type: 'array', type: 'array',
items: { items: {
$ref: '#/components/schemas/clientMetricsEnvSchema', $ref: '#/components/schemas/clientMetricsEnvSchema',

View File

@ -31,13 +31,15 @@ export const clientMetricsEnvSchema = {
}, },
yes: { yes: {
description: 'How many times the toggle evaluated to true', description: 'How many times the toggle evaluated to true',
type: 'number', type: 'integer',
example: 974, example: 974,
minimum: 0,
}, },
no: { no: {
description: 'How many times the toggle evaluated to false', description: 'How many times the toggle evaluated to false',
type: 'number', type: 'integer',
example: 50, example: 50,
minimum: 0,
}, },
variants: { variants: {
description: 'How many times each variant was returned', description: 'How many times each variant was returned',

View File

@ -5,18 +5,48 @@ export const clientMetricsSchema = {
$id: '#/components/schemas/clientMetricsSchema', $id: '#/components/schemas/clientMetricsSchema',
type: 'object', type: 'object',
required: ['appName', 'bucket'], required: ['appName', 'bucket'],
description:
'Client usage metrics, accumulated in buckets of hour by hour by default',
properties: { properties: {
appName: { type: 'string' }, appName: {
instanceId: { type: 'string' }, description:
environment: { type: 'string' }, 'The name of the application that is evaluating toggles',
type: 'string',
example: 'insurance-selector',
},
instanceId: {
description:
'A [(somewhat) unique identifier](https://docs.getunleash.io/reference/sdks/node#advanced-usage) for the application',
type: 'string',
example: 'application-name-dacb1234',
},
environment: {
description: 'Which environment the application is running in',
type: 'string',
example: 'development',
},
bucket: { bucket: {
type: 'object', type: 'object',
required: ['start', 'stop', 'toggles'], required: ['start', 'stop', 'toggles'],
description:
'Holds all metrics gathered over a window of time. Typically 1 hour wide',
properties: { properties: {
start: { $ref: '#/components/schemas/dateSchema' }, start: {
stop: { $ref: '#/components/schemas/dateSchema' }, $ref: '#/components/schemas/dateSchema',
description:
'The start of the time window these metrics are valid for. The window is usually 1 hour wide',
example: '1926-05-08T12:00:00.000Z',
},
stop: {
$ref: '#/components/schemas/dateSchema',
description:
'The end of the time window these metrics are valid for. The window is 1 hour wide',
example: '1926-05-08T13:00:00.000Z',
},
toggles: { toggles: {
type: 'object', type: 'object',
description:
'an object containing feature names with yes/no plus variant usage',
example: { example: {
myCoolToggle: { myCoolToggle: {
yes: 25, yes: 25,
@ -35,14 +65,33 @@ export const clientMetricsSchema = {
additionalProperties: { additionalProperties: {
type: 'object', type: 'object',
properties: { properties: {
yes: { type: 'integer', minimum: 0 }, yes: {
no: { type: 'integer', minimum: 0 }, description:
'How many times the toggle evaluated to true',
type: 'number',
example: 974,
minimum: 0,
},
no: {
description:
'How many times the toggle evaluated to false',
type: 'integer',
example: 50,
minimum: 0,
},
variants: { variants: {
description:
'How many times each variant was returned',
type: 'object', type: 'object',
additionalProperties: { additionalProperties: {
type: 'integer', type: 'integer',
minimum: 0, minimum: 0,
}, },
example: {
variantA: 15,
variantB: 25,
variantC: 5,
},
}, },
}, },
}, },

View File

@ -0,0 +1,52 @@
import { FromSchema } from 'json-schema-to-ts';
export const createApplicationSchema = {
$id: '#/components/schemas/createApplicationSchema',
type: 'object',
additionalProperties: true,
description: 'Reported application information from Unleash SDKs',
required: ['appName'],
properties: {
appName: {
description: 'Name of the application',
type: 'string',
example: 'accounting',
},
sdkVersion: {
description:
'Which SDK and version the application reporting uses. Typically represented as `<identifier>:<version>`',
type: 'string',
example: 'unleash-client-java:8.0.0',
},
strategies: {
description:
'Which [strategies](https://docs.getunleash.io/topics/the-anatomy-of-unleash#activation-strategies) the application has loaded. Useful when trying to figure out if your [custom strategy](https://docs.getunleash.io/reference/custom-activation-strategies) has been loaded in the SDK',
type: 'array',
items: {
type: 'string',
},
example: ['standard', 'gradualRollout', 'mySpecialCustomStrategy'],
},
url: {
description:
'A link to reference the application reporting the metrics. Could for instance be a GitHub link to the repository of the application',
type: 'string',
example: 'https://github.com/Unleash/unleash-client-proxy-js',
},
color: {
description: `Css color to be used to color the application's entry in the application list`,
type: 'string',
example: 'red',
},
icon: {
description: `An URL to an icon file to be used for the applications's entry in the application list`,
type: 'string',
example: 'https://github.com/favicon.ico',
},
},
components: {},
} as const;
export type CreateApplicationSchema = FromSchema<
typeof createApplicationSchema
>;

View File

@ -1,32 +1,51 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
import { dateSchema } from './date-schema';
export const featureEnvironmentMetricsSchema = { export const featureEnvironmentMetricsSchema = {
$id: '#/components/schemas/featureEnvironmentMetricsSchema', $id: '#/components/schemas/featureEnvironmentMetricsSchema',
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
required: ['environment', 'timestamp', 'yes', 'no'], required: ['environment', 'timestamp', 'yes', 'no'],
description:
'How many times `feautreName` was evaluated to `true` (yes) and `false` (no) for `appName` in `environmnet`',
properties: { properties: {
featureName: { featureName: {
description: 'The name of the feature',
type: 'string', type: 'string',
example: 'my.special.feature',
}, },
appName: { appName: {
description: 'The name of the application the SDK is being used in',
type: 'string', type: 'string',
example: 'accounting',
}, },
environment: { environment: {
description: 'Which environment the SDK is being used in',
type: 'string', type: 'string',
example: 'development',
}, },
timestamp: { timestamp: {
type: 'string', description:
format: 'date-time', 'The start of the time window these metrics are valid for. The window is usually 1 hour wide',
example: '1926-05-08T12:00:00.000Z',
$ref: '#/components/schemas/dateSchema',
}, },
yes: { yes: {
type: 'number', description: 'How many times the toggle evaluated to true',
type: 'integer',
example: 974,
minimum: 0,
}, },
no: { no: {
type: 'number', description: 'How many times the toggle evaluated to false',
type: 'integer',
example: 50,
minimum: 0,
}, },
}, },
components: {}, components: {
dateSchema,
},
} as const; } as const;
export type FeatureEnvironmentMetricsSchema = FromSchema< export type FeatureEnvironmentMetricsSchema = FromSchema<

View File

@ -1,19 +1,27 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
import { featureEnvironmentMetricsSchema } from './feature-environment-metrics-schema'; import { featureEnvironmentMetricsSchema } from './feature-environment-metrics-schema';
import { dateSchema } from './date-schema';
export const featureMetricsSchema = { export const featureMetricsSchema = {
$id: '#/components/schemas/featureMetricsSchema', $id: '#/components/schemas/featureMetricsSchema',
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
required: ['version', 'maturity', 'data'], required: ['version', 'maturity', 'data'],
description: 'A batch of feature metrics',
properties: { properties: {
version: { version: {
type: 'number', description: 'The version of this schema',
type: 'integer',
minimum: 1,
}, },
maturity: { maturity: {
description:
'The maturity level of this API (alpha, beta, stable, deprecated)',
type: 'string', type: 'string',
example: 'stable',
}, },
data: { data: {
description: 'Metrics gathered per environment',
type: 'array', type: 'array',
items: { items: {
$ref: '#/components/schemas/featureEnvironmentMetricsSchema', $ref: '#/components/schemas/featureEnvironmentMetricsSchema',
@ -23,6 +31,7 @@ export const featureMetricsSchema = {
components: { components: {
schemas: { schemas: {
featureEnvironmentMetricsSchema, featureEnvironmentMetricsSchema,
dateSchema,
}, },
}, },
} as const; } as const;

View File

@ -1,10 +1,13 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
import { featureEnvironmentMetricsSchema } from './feature-environment-metrics-schema'; import { featureEnvironmentMetricsSchema } from './feature-environment-metrics-schema';
import { dateSchema } from './date-schema';
export const featureUsageSchema = { export const featureUsageSchema = {
$id: '#/components/schemas/featureUsageSchema', $id: '#/components/schemas/featureUsageSchema',
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
description:
'How many applications have seen this feature toggle, as well as how this feature was evaluated the last hour',
required: [ required: [
'version', 'version',
'maturity', 'maturity',
@ -14,30 +17,42 @@ export const featureUsageSchema = {
], ],
properties: { properties: {
version: { version: {
type: 'number', description: 'The version of this schema',
type: 'integer',
minimum: 1,
}, },
maturity: { maturity: {
description:
'The maturity level of this API (alpha, beta, stable, deprecated)',
type: 'string', type: 'string',
example: 'stable',
}, },
featureName: { featureName: {
description: 'The name of the feature',
type: 'string', type: 'string',
example: 'my.special.feature',
}, },
lastHourUsage: { lastHourUsage: {
description:
'Last hour statistics. Accumulated per feature per environment. Contains counts for evaluations to true (yes) and to false (no)',
type: 'array', type: 'array',
items: { items: {
$ref: '#/components/schemas/featureEnvironmentMetricsSchema', $ref: '#/components/schemas/featureEnvironmentMetricsSchema',
}, },
}, },
seenApplications: { seenApplications: {
description: 'A list of applications seen using this feature',
type: 'array', type: 'array',
items: { items: {
type: 'string', type: 'string',
}, },
example: ['accounting', 'billing', 'booking'],
}, },
}, },
components: { components: {
schemas: { schemas: {
featureEnvironmentMetricsSchema, featureEnvironmentMetricsSchema,
dateSchema,
}, },
}, },
} as const; } as const;

View File

@ -16,6 +16,7 @@ import {
featureMetricsSchema, featureMetricsSchema,
FeatureMetricsSchema, FeatureMetricsSchema,
} from '../../openapi/spec/feature-metrics-schema'; } from '../../openapi/spec/feature-metrics-schema';
import { getStandardResponses } from '../../openapi';
interface IName { interface IName {
name: string; name: string;
@ -58,8 +59,11 @@ class ClientMetricsController extends Controller {
openApiService.validPath({ openApiService.validPath({
operationId: 'getRawFeatureMetrics', operationId: 'getRawFeatureMetrics',
tags: ['Metrics'], tags: ['Metrics'],
summary:
'Feature usage metrics for the last 48 hours, grouped by hour',
responses: { responses: {
200: createResponseSchema('featureMetricsSchema'), 200: createResponseSchema('featureMetricsSchema'),
...getStandardResponses(401, 403, 404),
}, },
}), }),
], ],
@ -74,8 +78,12 @@ class ClientMetricsController extends Controller {
openApiService.validPath({ openApiService.validPath({
operationId: 'getFeatureUsageSummary', operationId: 'getFeatureUsageSummary',
tags: ['Metrics'], tags: ['Metrics'],
summary: `Last hour of usage and a list of applications that have reported seeing this feature toggle`,
description:
'Separate counts for yes (enabled), no (disabled), as well as how many times each variant was selected during the last hour',
responses: { responses: {
200: createResponseSchema('featureUsageSchema'), 200: createResponseSchema('featureUsageSchema'),
...getStandardResponses(401, 403, 404),
}, },
}), }),
], ],

View File

@ -9,7 +9,11 @@ import { createRequestSchema } from '../../openapi/util/create-request-schema';
import { createResponseSchema } from '../../openapi/util/create-response-schema'; import { createResponseSchema } from '../../openapi/util/create-response-schema';
import { ApplicationSchema } from '../../openapi/spec/application-schema'; import { ApplicationSchema } from '../../openapi/spec/application-schema';
import { ApplicationsSchema } from '../../openapi/spec/applications-schema'; import { ApplicationsSchema } from '../../openapi/spec/applications-schema';
import { emptyResponse } from '../../openapi/util/standard-responses'; import {
emptyResponse,
getStandardResponses,
} from '../../openapi/util/standard-responses';
import { CreateApplicationSchema } from '../../openapi/spec/create-application-schema';
class MetricsController extends Controller { class MetricsController extends Controller {
private logger: Logger; private logger: Logger;
@ -43,10 +47,15 @@ class MetricsController extends Controller {
openApiService.validPath({ openApiService.validPath({
tags: ['Metrics'], tags: ['Metrics'],
operationId: 'createApplication', operationId: 'createApplication',
summary:
'Create an application to connect reported metrics',
description:
'Is used to report usage as well which sdk the application uses',
responses: { responses: {
202: emptyResponse, 202: emptyResponse,
...getStandardResponses(400, 401, 403),
}, },
requestBody: createRequestSchema('applicationSchema'), requestBody: createRequestSchema('createApplicationSchema'),
}), }),
], ],
}); });
@ -60,8 +69,11 @@ class MetricsController extends Controller {
openApiService.validPath({ openApiService.validPath({
tags: ['Metrics'], tags: ['Metrics'],
operationId: 'deleteApplication', operationId: 'deleteApplication',
summary: 'Delete an application',
description: `Delete the application specified in the request URL. Returns 200 OK if the application was successfully deleted or if it didn't exist`,
responses: { responses: {
200: emptyResponse, 200: emptyResponse,
...getStandardResponses(401, 403),
}, },
}), }),
], ],
@ -74,6 +86,9 @@ class MetricsController extends Controller {
middleware: [ middleware: [
openApiService.validPath({ openApiService.validPath({
tags: ['Metrics'], tags: ['Metrics'],
summary: 'Get all applications',
description:
'Returns all applications registered with Unleash. Applications can be created via metrics reporting or manual creation',
operationId: 'getApplications', operationId: 'getApplications',
responses: { responses: {
200: createResponseSchema('applicationsSchema'), 200: createResponseSchema('applicationsSchema'),
@ -90,8 +105,12 @@ class MetricsController extends Controller {
openApiService.validPath({ openApiService.validPath({
tags: ['Metrics'], tags: ['Metrics'],
operationId: 'getApplication', operationId: 'getApplication',
summary: 'Get application data',
description:
'Returns data about the specified application (`appName`). The data contains information on the name of the application, sdkVersion (which sdk reported these metrics, typically `unleash-client-node:3.4.1` or `unleash-client-java:7.1.0`), as well as data about how to display this application in a list.',
responses: { responses: {
200: createResponseSchema('applicationSchema'), 200: createResponseSchema('applicationSchema'),
...getStandardResponses(404),
}, },
}), }),
], ],
@ -117,7 +136,7 @@ class MetricsController extends Controller {
} }
async createApplication( async createApplication(
req: Request<{ appName: string }, unknown, ApplicationSchema>, req: Request<{ appName: string }, unknown, CreateApplicationSchema>,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
const input = { const input = {

View File

@ -703,31 +703,46 @@ The provider you choose for your addon dictates what properties the \`parameters
"applicationSchema": { "applicationSchema": {
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"announced": {
"type": "boolean",
},
"appName": { "appName": {
"description": "Name of the application",
"example": "accounting",
"type": "string", "type": "string",
}, },
"color": { "color": {
"description": "The CSS color that is used to color the application's entry in the application list",
"example": "red",
"type": "string", "type": "string",
}, },
"description": { "description": {
"description": "Extra information added about the application reporting the metrics. Only present if added via the Unleash Admin interface",
"example": "Application for reporting page visits",
"type": "string", "type": "string",
}, },
"icon": { "icon": {
"description": "An URL to an icon file to be used for the applications's entry in the application list",
"example": "https://github.com/favicon.ico",
"type": "string", "type": "string",
}, },
"sdkVersion": { "sdkVersion": {
"description": "Which SDK and version the application reporting uses. Typically represented as \`<identifier>:<version>\`",
"example": "unleash-client-java:8.0.0",
"type": "string", "type": "string",
}, },
"strategies": { "strategies": {
"description": "Which [strategies](https://docs.getunleash.io/topics/the-anatomy-of-unleash#activation-strategies) the application has loaded. Useful when trying to figure out if your [custom strategy](https://docs.getunleash.io/reference/custom-activation-strategies) has been loaded in the SDK",
"example": [
"standard",
"gradualRollout",
"mySpecialCustomStrategy",
],
"items": { "items": {
"type": "string", "type": "string",
}, },
"type": "array", "type": "array",
}, },
"url": { "url": {
"description": "A link to reference the application reporting the metrics. Could for instance be a GitHub link to the repository of the application",
"example": "https://github.com/Unleash/unleash-client-proxy-js",
"type": "string", "type": "string",
}, },
}, },
@ -737,8 +752,10 @@ The provider you choose for your addon dictates what properties the \`parameters
"type": "object", "type": "object",
}, },
"applicationsSchema": { "applicationsSchema": {
"additionalProperties": false,
"properties": { "properties": {
"applications": { "applications": {
"description": "Contains a list of applications that have connected via an SDK",
"items": { "items": {
"$ref": "#/components/schemas/applicationSchema", "$ref": "#/components/schemas/applicationSchema",
}, },
@ -783,12 +800,14 @@ The provider you choose for your addon dictates what properties the \`parameters
"description": "A batch of metrics accumulated by Edge (or other compatible applications). Includes both application registrations as well usage metrics from clients", "description": "A batch of metrics accumulated by Edge (or other compatible applications). Includes both application registrations as well usage metrics from clients",
"properties": { "properties": {
"applications": { "applications": {
"description": "A list of applications registered by an Unleash SDK",
"items": { "items": {
"$ref": "#/components/schemas/bulkRegistrationSchema", "$ref": "#/components/schemas/bulkRegistrationSchema",
}, },
"type": "array", "type": "array",
}, },
"metrics": { "metrics": {
"description": "a list of client usage metrics registered by downstream providers. (Typically Unleash Edge)",
"items": { "items": {
"$ref": "#/components/schemas/clientMetricsEnvSchema", "$ref": "#/components/schemas/clientMetricsEnvSchema",
}, },
@ -1075,7 +1094,8 @@ The provider you choose for your addon dictates what properties the \`parameters
"no": { "no": {
"description": "How many times the toggle evaluated to false", "description": "How many times the toggle evaluated to false",
"example": 50, "example": 50,
"type": "number", "minimum": 0,
"type": "integer",
}, },
"timestamp": { "timestamp": {
"$ref": "#/components/schemas/dateSchema", "$ref": "#/components/schemas/dateSchema",
@ -1098,7 +1118,8 @@ The provider you choose for your addon dictates what properties the \`parameters
"yes": { "yes": {
"description": "How many times the toggle evaluated to true", "description": "How many times the toggle evaluated to true",
"example": 974, "example": 974,
"type": "number", "minimum": 0,
"type": "integer",
}, },
}, },
"required": [ "required": [
@ -1109,22 +1130,32 @@ The provider you choose for your addon dictates what properties the \`parameters
"type": "object", "type": "object",
}, },
"clientMetricsSchema": { "clientMetricsSchema": {
"description": "Client usage metrics, accumulated in buckets of hour by hour by default",
"properties": { "properties": {
"appName": { "appName": {
"description": "The name of the application that is evaluating toggles",
"example": "insurance-selector",
"type": "string", "type": "string",
}, },
"bucket": { "bucket": {
"description": "Holds all metrics gathered over a window of time. Typically 1 hour wide",
"properties": { "properties": {
"start": { "start": {
"$ref": "#/components/schemas/dateSchema", "$ref": "#/components/schemas/dateSchema",
"description": "The start of the time window these metrics are valid for. The window is usually 1 hour wide",
"example": "1926-05-08T12:00:00.000Z",
}, },
"stop": { "stop": {
"$ref": "#/components/schemas/dateSchema", "$ref": "#/components/schemas/dateSchema",
"description": "The end of the time window these metrics are valid for. The window is 1 hour wide",
"example": "1926-05-08T13:00:00.000Z",
}, },
"toggles": { "toggles": {
"additionalProperties": { "additionalProperties": {
"properties": { "properties": {
"no": { "no": {
"description": "How many times the toggle evaluated to false",
"example": 50,
"minimum": 0, "minimum": 0,
"type": "integer", "type": "integer",
}, },
@ -1133,15 +1164,24 @@ The provider you choose for your addon dictates what properties the \`parameters
"minimum": 0, "minimum": 0,
"type": "integer", "type": "integer",
}, },
"description": "How many times each variant was returned",
"example": {
"variantA": 15,
"variantB": 25,
"variantC": 5,
},
"type": "object", "type": "object",
}, },
"yes": { "yes": {
"description": "How many times the toggle evaluated to true",
"example": 974,
"minimum": 0, "minimum": 0,
"type": "integer", "type": "number",
}, },
}, },
"type": "object", "type": "object",
}, },
"description": "an object containing feature names with yes/no plus variant usage",
"example": { "example": {
"myCoolToggle": { "myCoolToggle": {
"no": 42, "no": 42,
@ -1168,9 +1208,13 @@ The provider you choose for your addon dictates what properties the \`parameters
"type": "object", "type": "object",
}, },
"environment": { "environment": {
"description": "Which environment the application is running in",
"example": "development",
"type": "string", "type": "string",
}, },
"instanceId": { "instanceId": {
"description": "A [(somewhat) unique identifier](https://docs.getunleash.io/reference/sdks/node#advanced-usage) for the application",
"example": "application-name-dacb1234",
"type": "string", "type": "string",
}, },
}, },
@ -1332,6 +1376,53 @@ The provider you choose for your addon dictates what properties the \`parameters
], ],
"type": "object", "type": "object",
}, },
"createApplicationSchema": {
"additionalProperties": true,
"description": "Reported application information from Unleash SDKs",
"properties": {
"appName": {
"description": "Name of the application",
"example": "accounting",
"type": "string",
},
"color": {
"description": "Css color to be used to color the application's entry in the application list",
"example": "red",
"type": "string",
},
"icon": {
"description": "An URL to an icon file to be used for the applications's entry in the application list",
"example": "https://github.com/favicon.ico",
"type": "string",
},
"sdkVersion": {
"description": "Which SDK and version the application reporting uses. Typically represented as \`<identifier>:<version>\`",
"example": "unleash-client-java:8.0.0",
"type": "string",
},
"strategies": {
"description": "Which [strategies](https://docs.getunleash.io/topics/the-anatomy-of-unleash#activation-strategies) the application has loaded. Useful when trying to figure out if your [custom strategy](https://docs.getunleash.io/reference/custom-activation-strategies) has been loaded in the SDK",
"example": [
"standard",
"gradualRollout",
"mySpecialCustomStrategy",
],
"items": {
"type": "string",
},
"type": "array",
},
"url": {
"description": "A link to reference the application reporting the metrics. Could for instance be a GitHub link to the repository of the application",
"example": "https://github.com/Unleash/unleash-client-proxy-js",
"type": "string",
},
},
"required": [
"appName",
],
"type": "object",
},
"createFeatureSchema": { "createFeatureSchema": {
"properties": { "properties": {
"description": { "description": {
@ -1849,25 +1940,39 @@ The provider you choose for your addon dictates what properties the \`parameters
}, },
"featureEnvironmentMetricsSchema": { "featureEnvironmentMetricsSchema": {
"additionalProperties": false, "additionalProperties": false,
"description": "How many times \`feautreName\` was evaluated to \`true\` (yes) and \`false\` (no) for \`appName\` in \`environmnet\`",
"properties": { "properties": {
"appName": { "appName": {
"description": "The name of the application the SDK is being used in",
"example": "accounting",
"type": "string", "type": "string",
}, },
"environment": { "environment": {
"description": "Which environment the SDK is being used in",
"example": "development",
"type": "string", "type": "string",
}, },
"featureName": { "featureName": {
"description": "The name of the feature",
"example": "my.special.feature",
"type": "string", "type": "string",
}, },
"no": { "no": {
"type": "number", "description": "How many times the toggle evaluated to false",
"example": 50,
"minimum": 0,
"type": "integer",
}, },
"timestamp": { "timestamp": {
"format": "date-time", "$ref": "#/components/schemas/dateSchema",
"type": "string", "description": "The start of the time window these metrics are valid for. The window is usually 1 hour wide",
"example": "1926-05-08T12:00:00.000Z",
}, },
"yes": { "yes": {
"type": "number", "description": "How many times the toggle evaluated to true",
"example": 974,
"minimum": 0,
"type": "integer",
}, },
}, },
"required": [ "required": [
@ -1960,18 +2065,24 @@ The provider you choose for your addon dictates what properties the \`parameters
}, },
"featureMetricsSchema": { "featureMetricsSchema": {
"additionalProperties": false, "additionalProperties": false,
"description": "A batch of feature metrics",
"properties": { "properties": {
"data": { "data": {
"description": "Metrics gathered per environment",
"items": { "items": {
"$ref": "#/components/schemas/featureEnvironmentMetricsSchema", "$ref": "#/components/schemas/featureEnvironmentMetricsSchema",
}, },
"type": "array", "type": "array",
}, },
"maturity": { "maturity": {
"description": "The maturity level of this API (alpha, beta, stable, deprecated)",
"example": "stable",
"type": "string", "type": "string",
}, },
"version": { "version": {
"type": "number", "description": "The version of this schema",
"minimum": 1,
"type": "integer",
}, },
}, },
"required": [ "required": [
@ -2245,27 +2356,41 @@ The provider you choose for your addon dictates what properties the \`parameters
}, },
"featureUsageSchema": { "featureUsageSchema": {
"additionalProperties": false, "additionalProperties": false,
"description": "How many applications have seen this feature toggle, as well as how this feature was evaluated the last hour",
"properties": { "properties": {
"featureName": { "featureName": {
"description": "The name of the feature",
"example": "my.special.feature",
"type": "string", "type": "string",
}, },
"lastHourUsage": { "lastHourUsage": {
"description": "Last hour statistics. Accumulated per feature per environment. Contains counts for evaluations to true (yes) and to false (no)",
"items": { "items": {
"$ref": "#/components/schemas/featureEnvironmentMetricsSchema", "$ref": "#/components/schemas/featureEnvironmentMetricsSchema",
}, },
"type": "array", "type": "array",
}, },
"maturity": { "maturity": {
"description": "The maturity level of this API (alpha, beta, stable, deprecated)",
"example": "stable",
"type": "string", "type": "string",
}, },
"seenApplications": { "seenApplications": {
"description": "A list of applications seen using this feature",
"example": [
"accounting",
"billing",
"booking",
],
"items": { "items": {
"type": "string", "type": "string",
}, },
"type": "array", "type": "array",
}, },
"version": { "version": {
"type": "number", "description": "The version of this schema",
"minimum": 1,
"type": "integer",
}, },
}, },
"required": [ "required": [
@ -5913,6 +6038,7 @@ Note: passing \`null\` as a value for the description property will set it to an
}, },
"/api/admin/client-metrics/features/{name}": { "/api/admin/client-metrics/features/{name}": {
"get": { "get": {
"description": "Separate counts for yes (enabled), no (disabled), as well as how many times each variant was selected during the last hour",
"operationId": "getFeatureUsageSummary", "operationId": "getFeatureUsageSummary",
"parameters": [ "parameters": [
{ {
@ -5935,7 +6061,89 @@ Note: passing \`null\` as a value for the description property will set it to an
}, },
"description": "featureUsageSchema", "description": "featureUsageSchema",
}, },
"401": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "AuthenticationRequired",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.",
},
"403": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NoAccessError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "User credentials are valid but does not have enough privileges to execute this operation",
},
"404": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "Could not find the addon with ID "12345".",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NotFoundError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "The requested resource was not found.",
},
}, },
"summary": "Last hour of usage and a list of applications that have reported seeing this feature toggle",
"tags": [ "tags": [
"Metrics", "Metrics",
], ],
@ -5965,7 +6173,89 @@ Note: passing \`null\` as a value for the description property will set it to an
}, },
"description": "featureMetricsSchema", "description": "featureMetricsSchema",
}, },
"401": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "AuthenticationRequired",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.",
},
"403": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NoAccessError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "User credentials are valid but does not have enough privileges to execute this operation",
},
"404": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "Could not find the addon with ID "12345".",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NotFoundError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "The requested resource was not found.",
},
}, },
"summary": "Feature usage metrics for the last 48 hours, grouped by hour",
"tags": [ "tags": [
"Metrics", "Metrics",
], ],
@ -8202,6 +8492,7 @@ If the provided project does not exist, the list of events will be empty.",
}, },
"/api/admin/metrics/applications": { "/api/admin/metrics/applications": {
"get": { "get": {
"description": "Returns all applications registered with Unleash. Applications can be created via metrics reporting or manual creation",
"operationId": "getApplications", "operationId": "getApplications",
"responses": { "responses": {
"200": { "200": {
@ -8215,6 +8506,7 @@ If the provided project does not exist, the list of events will be empty.",
"description": "applicationsSchema", "description": "applicationsSchema",
}, },
}, },
"summary": "Get all applications",
"tags": [ "tags": [
"Metrics", "Metrics",
], ],
@ -8222,6 +8514,7 @@ If the provided project does not exist, the list of events will be empty.",
}, },
"/api/admin/metrics/applications/{appName}": { "/api/admin/metrics/applications/{appName}": {
"delete": { "delete": {
"description": "Delete the application specified in the request URL. Returns 200 OK if the application was successfully deleted or if it didn't exist",
"operationId": "deleteApplication", "operationId": "deleteApplication",
"parameters": [ "parameters": [
{ {
@ -8237,12 +8530,68 @@ If the provided project does not exist, the list of events will be empty.",
"200": { "200": {
"description": "This response has no body.", "description": "This response has no body.",
}, },
"401": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "AuthenticationRequired",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.",
},
"403": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NoAccessError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "User credentials are valid but does not have enough privileges to execute this operation",
},
}, },
"summary": "Delete an application",
"tags": [ "tags": [
"Metrics", "Metrics",
], ],
}, },
"get": { "get": {
"description": "Returns data about the specified application (\`appName\`). The data contains information on the name of the application, sdkVersion (which sdk reported these metrics, typically \`unleash-client-node:3.4.1\` or \`unleash-client-java:7.1.0\`), as well as data about how to display this application in a list.",
"operationId": "getApplication", "operationId": "getApplication",
"parameters": [ "parameters": [
{ {
@ -8265,12 +8614,41 @@ If the provided project does not exist, the list of events will be empty.",
}, },
"description": "applicationSchema", "description": "applicationSchema",
}, },
"404": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "Could not find the addon with ID "12345".",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NotFoundError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "The requested resource was not found.",
},
}, },
"summary": "Get application data",
"tags": [ "tags": [
"Metrics", "Metrics",
], ],
}, },
"post": { "post": {
"description": "Is used to report usage as well which sdk the application uses",
"operationId": "createApplication", "operationId": "createApplication",
"parameters": [ "parameters": [
{ {
@ -8286,18 +8664,100 @@ If the provided project does not exist, the list of events will be empty.",
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "#/components/schemas/applicationSchema", "$ref": "#/components/schemas/createApplicationSchema",
}, },
}, },
}, },
"description": "applicationSchema", "description": "createApplicationSchema",
"required": true, "required": true,
}, },
"responses": { "responses": {
"202": { "202": {
"description": "This response has no body.", "description": "This response has no body.",
}, },
"400": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "ValidationError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "The request data does not match what we expect.",
},
"401": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "AuthenticationRequired",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.",
},
"403": {
"content": {
"application/json": {
"schema": {
"properties": {
"id": {
"description": "The ID of the error instance",
"example": "9c40958a-daac-400e-98fb-3bb438567008",
"type": "string",
},
"message": {
"description": "A description of what went wrong.",
"example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.",
"type": "string",
},
"name": {
"description": "The name of the error kind",
"example": "NoAccessError",
"type": "string",
},
},
"type": "object",
},
},
},
"description": "User credentials are valid but does not have enough privileges to execute this operation",
},
}, },
"summary": "Create an application to connect reported metrics",
"tags": [ "tags": [
"Metrics", "Metrics",
], ],