mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-12 01:17:04 +02:00
OAS for client-metrics controller (#1739)
* OAS for client-metrics controller * bug and tests * update snapshot * update snapshot * update snapshot * bug fix * fix PR comments * refactoring re PR comments * re order routes * remove grouped-client-metrics-schema.ts * remove grouped-client-metrics-schema.ts * updated response * updated snapshot * PR comments * PR comments * Added tests * Added tests * fix * fix * fix
This commit is contained in:
parent
4c3ac89f7b
commit
64082440d4
47
README.md
47
README.md
@ -4,21 +4,16 @@
|
||||
<img src="./.github/github_header_opaque_landscape.svg" alt="The Unleash website">
|
||||
</a>
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
[](https://github.com/Unleash/unleash/actions/workflows/build.yaml)
|
||||
[](https://coveralls.io/github/Unleash/unleash?branch=main)
|
||||
[](https://hub.docker.com/r/unleashorg/unleash-server)
|
||||
[](https://github.com/Unleash/unleash/blob/main/LICENSE)
|
||||
[](https://slack.unleash.run)
|
||||
[](https://github.com/Unleash/unleash/actions/workflows/build.yaml) [](https://coveralls.io/github/Unleash/unleash?branch=main) [](https://hub.docker.com/r/unleashorg/unleash-server) [](https://github.com/Unleash/unleash/blob/main/LICENSE) [](https://slack.unleash.run)
|
||||
|
||||
</div>
|
||||
|
||||
## About Unleash
|
||||
|
||||
Unleash is an open source feature management solution. It improves the workflow of your development team and leads to quicker software delivery. Unleash increases efficiency and gives teams *full control* of how and when they enable new functionality for end users. Unleash lets teams ship code to production in *smaller* releases *whenever* they want.
|
||||
Unleash is an open source feature management solution. It improves the workflow of your development team and leads to quicker software delivery. Unleash increases efficiency and gives teams _full control_ of how and when they enable new functionality for end users. Unleash lets teams ship code to production in _smaller_ releases _whenever_ they want.
|
||||
|
||||
Feature toggles make it easy to test how your code works with real production data without the fear that you'll accidentally break your users' experience. It also helps your team work on multiple features in parallel without each maintaining an separate feature branch.
|
||||
|
||||
@ -33,15 +28,17 @@ Unleash is the largest open source solution for feature flagging on GitHub. Ther
|
||||
With [`git`](https://git-scm.com/) and [`docker`](https://www.docker.com/) installed, it's easy to get started:
|
||||
|
||||
Run this script:
|
||||
``` bash
|
||||
|
||||
```bash
|
||||
git clone git@github.com:Unleash/unleash-docker.git
|
||||
cd unleash-docker
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Then point your browser to `localhost:4242` and log in using:
|
||||
- username: `admin`
|
||||
- password: `unleash4all`
|
||||
|
||||
- username: `admin`
|
||||
- password: `unleash4all`
|
||||
|
||||
If you'd rather run the source code in this repo directly via Node.js, see the [step-by-step instructions to get up and running in the contributing guide](./CONTRIBUTING.md#how-to-run-the-project).
|
||||
|
||||
@ -50,11 +47,12 @@ If you'd rather run the source code in this repo directly via Node.js, see the [
|
||||
Find your preferred SDK in [our list of official SDKs](#unleash-sdks) and import it into your project. Follow the setup guides for your specific SDK.
|
||||
|
||||
If you use the docker compose file from the previous step, here's the configuration details you'll need to get going:
|
||||
|
||||
- For front-end SDKs, use:
|
||||
- URL: `http://localhost:3000`
|
||||
- `clientKey`: `proxy-client-key`
|
||||
- For server-side SDKs, use:
|
||||
- Unleash API URL: `http://localhost:4242`
|
||||
- Unleash API URL: `http://localhost:4242/api/`
|
||||
- API token: `default:development.unleash-insecure-api-token`
|
||||
|
||||
If you use a different setup, your configuration details will most likely also be different.
|
||||
@ -107,9 +105,7 @@ We know that learning a new tool can be hard and time-consuming. We have a growi
|
||||
|
||||
## Contribute to Unleash
|
||||
|
||||
Building Unleash is a collaborative effort, and we owe a lot of gratitude to many smart and talented individuals.
|
||||
Building it together with community ensures that we build a product that solves real problems for real people.
|
||||
We'd love to have your help too: Please feel free to open issues or provide pull requests.
|
||||
Building Unleash is a collaborative effort, and we owe a lot of gratitude to many smart and talented individuals. Building it together with community ensures that we build a product that solves real problems for real people. We'd love to have your help too: Please feel free to open issues or provide pull requests.
|
||||
|
||||
Check out [the CONTRIBUTING.md file](./CONTRIBUTING.md) for contribution guidelines and the [Unleash developer guide](./website/docs/contributing/developer-guide.md) for tips on environment setup, running the tests, and running Unleash from source.
|
||||
|
||||
@ -137,7 +133,7 @@ Check out [the CONTRIBUTING.md file](./CONTRIBUTING.md) for contribution guideli
|
||||
- 2 [environments](https://docs.getunleash.io/user_guide/environments)
|
||||
- Out-of-the-box integrations with popular tools ([Slack](https://docs.getunleash.io/addons/slack), [Microsoft Teams](https://docs.getunleash.io/addons/teams), [Datadog](https://docs.getunleash.io/addons/datadog)) + integrate with anything with [webhooks](https://docs.getunleash.io/addons/webhook)
|
||||
- [Dashboard for managing technical debt](https://docs.getunleash.io/user_guide/technical_debt) and [stale toggles](https://docs.getunleash.io/user_guide/technical_debt#stale-and-potentially-stale-toggles)
|
||||
- API-first: *everything* can be automated. No exceptions.
|
||||
- API-first: _everything_ can be automated. No exceptions.
|
||||
- [12 official client SDKs](https://docs.getunleash.io/sdks#official-sdks), and ten [community-contributed client SDKs](https://docs.getunleash.io/sdks#community-sdks)
|
||||
- Run it via Docker with the [official Docker image](https://hub.docker.com/r/unleashorg/unleash-server) or as a pure Node.js application
|
||||
|
||||
@ -146,12 +142,13 @@ Check out [the CONTRIBUTING.md file](./CONTRIBUTING.md) for contribution guideli
|
||||
- Privacy by design (GDPR and Schrems II). End-user data never leaves your application.
|
||||
- [Audit logs](https://docs.getunleash.io/advanced/audit_log)
|
||||
- Enforce [OWASP's secure headers](https://owasp.org/www-project-secure-headers/) via the strict HTTPS-only mode
|
||||
- Flexible hosting options: host it on premise or in the cloud (*any* cloud)
|
||||
- Flexible hosting options: host it on premise or in the cloud (_any_ cloud)
|
||||
- Scale [the Unleash Proxy](https://docs.getunleash.io/sdks/unleash-proxy) independently of the Unleash server to support any number of front-end clients without overloading your Unleash instance
|
||||
|
||||
### Looking for more features?
|
||||
|
||||
If you're looking for one of the following features, please take a look at our [Pro and Enterprise plans](https://www.getunleash.io/plans):
|
||||
|
||||
- [role-based access control (RBAC)](https://docs.getunleash.io/user_guide/rbac)
|
||||
- [single sign-on (SSO)](https://docs.getunleash.io/advanced/enterprise-authentication)
|
||||
- more environments
|
||||
@ -167,7 +164,7 @@ If you're looking for one of the following features, please take a look at our [
|
||||
|
||||
<img src="./website/static/img/unleash-architecture.svg" title="Unleash System Overview" />
|
||||
|
||||
Read more in the [*system overview* section of the Unleash documentation](https://docs.getunleash.io/user_guide/unleash_overview#system-overview).
|
||||
Read more in the [_system overview_ section of the Unleash documentation](https://docs.getunleash.io/user_guide/unleash_overview#system-overview).
|
||||
|
||||
<br/>
|
||||
|
||||
@ -216,15 +213,15 @@ If none of the official SDKs fit your need, there's also a number of [community-
|
||||
### Videos and podcasts
|
||||
|
||||
- [The Unleash YouTube channel](https://www.youtube.com/channel/UCJjGVOc5QBbEje-r7nZEa4A)
|
||||
- [*Feature toggles — Why and how to add to your software* — freeCodeCamp (YouTube)](https://www.youtube.com/watch?v=-yHZ9uLVSp4&t=0s)
|
||||
- [*Feature flags with Unleash* — The Code Kitchen (podcast)](https://share.fireside.fm/episode/zD-4e4KI+Pr379KBv)
|
||||
- [*Feature Flags og Unleash med Fredrik Oseberg* — Utviklerpodden (podcast; Norwegian)](https://pod.space/utviklerpodden/feature-flags-og-unleash-med-fredrik-oseberg)
|
||||
- [_Feature toggles — Why and how to add to your software_ — freeCodeCamp (YouTube)](https://www.youtube.com/watch?v=-yHZ9uLVSp4&t=0s)
|
||||
- [_Feature flags with Unleash_ — The Code Kitchen (podcast)](https://share.fireside.fm/episode/zD-4e4KI+Pr379KBv)
|
||||
- [_Feature Flags og Unleash med Fredrik Oseberg_ — Utviklerpodden (podcast; Norwegian)](https://pod.space/utviklerpodden/feature-flags-og-unleash-med-fredrik-oseberg)
|
||||
|
||||
### Articles and more
|
||||
|
||||
- [The Unleash Blog](https://www.getunleash.io/blog)
|
||||
- [*Designing the Rust Unleash API client* — Medium](https://medium.com/cognite/designing-the-rust-unleash-api-client-6809c95aa568)
|
||||
- [*FeatureToggle* by Martin Fowler](http://martinfowler.com/bliki/FeatureToggle.html)
|
||||
- [*Feature toggling transient errors in load tests* — nrkbeta](https://nrkbeta.no/2021/08/23/feature-toggling-transient-errors-in-load-tests/)
|
||||
- [*An Interview with Ivar of Unleash* — Console](https://console.substack.com/p/console-42)
|
||||
- [*Unleash your features gradually*](http://ivarconr.github.io/feature-toggles-presentation/sch-dev-lunch-2017/#1 " "), slideshow/presentation by Ivar, the creator of Unleash
|
||||
- [_Designing the Rust Unleash API client_ — Medium](https://medium.com/cognite/designing-the-rust-unleash-api-client-6809c95aa568)
|
||||
- [_FeatureToggle_ by Martin Fowler](http://martinfowler.com/bliki/FeatureToggle.html)
|
||||
- [_Feature toggling transient errors in load tests_ — nrkbeta](https://nrkbeta.no/2021/08/23/feature-toggling-transient-errors-in-load-tests/)
|
||||
- [_An Interview with Ivar of Unleash_ — Console](https://console.substack.com/p/console-42)
|
||||
- [_Unleash your features gradually_](http://ivarconr.github.io/feature-toggles-presentation/sch-dev-lunch-2017/#1 ' '), slideshow/presentation by Ivar, the creator of Unleash
|
||||
|
@ -59,6 +59,9 @@ import { validateTagTypeSchema } from './spec/validate-tag-type-schema';
|
||||
import { variantSchema } from './spec/variant-schema';
|
||||
import { variantsSchema } from './spec/variants-schema';
|
||||
import { versionSchema } from './spec/version-schema';
|
||||
import { featureEnvironmentMetricsSchema } from './spec/feature-environment-metrics-schema';
|
||||
import { featureUsageSchema } from './spec/feature-usage-schema';
|
||||
import { featureMetricsSchema } from './spec/feature-metrics-schema';
|
||||
import { addonSchema } from './spec/addon-schema';
|
||||
import { addonsSchema } from './spec/addons-schema';
|
||||
import { addonParameterSchema } from './spec/addon-parameter-schema';
|
||||
@ -106,7 +109,10 @@ export const schemas = {
|
||||
environmentsSchema,
|
||||
exportParametersSchema,
|
||||
featureEnvironmentSchema,
|
||||
featureEnvironmentMetricsSchema,
|
||||
featureSchema,
|
||||
featureMetricsSchema,
|
||||
featureUsageSchema,
|
||||
featureStrategySchema,
|
||||
featureStrategySegmentSchema,
|
||||
featureTagSchema,
|
||||
|
34
src/lib/openapi/spec/feature-environment-metrics-schema.ts
Normal file
34
src/lib/openapi/spec/feature-environment-metrics-schema.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { FromSchema } from 'json-schema-to-ts';
|
||||
|
||||
export const featureEnvironmentMetricsSchema = {
|
||||
$id: '#/components/schemas/featureEnvironmentMetricsSchema',
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['environment', 'timestamp', 'yes', 'no'],
|
||||
properties: {
|
||||
featureName: {
|
||||
type: 'string',
|
||||
},
|
||||
appName: {
|
||||
type: 'string',
|
||||
},
|
||||
environment: {
|
||||
type: 'string',
|
||||
},
|
||||
timestamp: {
|
||||
type: 'string',
|
||||
format: 'date-time',
|
||||
},
|
||||
yes: {
|
||||
type: 'number',
|
||||
},
|
||||
no: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
components: {},
|
||||
} as const;
|
||||
|
||||
export type FeatureEnvironmentMetricsSchema = FromSchema<
|
||||
typeof featureEnvironmentMetricsSchema
|
||||
>;
|
21
src/lib/openapi/spec/feature-metrics-schema.test.ts
Normal file
21
src/lib/openapi/spec/feature-metrics-schema.test.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { validateSchema } from '../validate';
|
||||
import { FeatureMetricsSchema } from './feature-metrics-schema';
|
||||
|
||||
test('featureMetricsSchema', () => {
|
||||
const data: FeatureMetricsSchema = {
|
||||
maturity: 'stable',
|
||||
version: 2,
|
||||
data: [
|
||||
{
|
||||
environment: 'some-env',
|
||||
timestamp: new Date(2020, 6, 1, 17, 50, 3).toISOString(),
|
||||
yes: 50,
|
||||
no: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(
|
||||
validateSchema('#/components/schemas/featureMetricsSchema', data),
|
||||
).toBeUndefined();
|
||||
});
|
30
src/lib/openapi/spec/feature-metrics-schema.ts
Normal file
30
src/lib/openapi/spec/feature-metrics-schema.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { featureEnvironmentMetricsSchema } from './feature-environment-metrics-schema';
|
||||
|
||||
export const featureMetricsSchema = {
|
||||
$id: '#/components/schemas/featureMetricsSchema',
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['version', 'maturity', 'data'],
|
||||
properties: {
|
||||
version: {
|
||||
type: 'number',
|
||||
},
|
||||
maturity: {
|
||||
type: 'string',
|
||||
},
|
||||
data: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/featureEnvironmentMetricsSchema',
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
featureEnvironmentMetricsSchema,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export type FeatureMetricsSchema = FromSchema<typeof featureMetricsSchema>;
|
23
src/lib/openapi/spec/feature-usage-schema.test.ts
Normal file
23
src/lib/openapi/spec/feature-usage-schema.test.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { validateSchema } from '../validate';
|
||||
import { FeatureUsageSchema } from './feature-usage-schema';
|
||||
|
||||
test('featureUsageSchema', () => {
|
||||
const data: FeatureUsageSchema = {
|
||||
featureName: 'some-name',
|
||||
version: 2,
|
||||
lastHourUsage: [
|
||||
{
|
||||
environment: 'some-env',
|
||||
yes: 50,
|
||||
no: 32,
|
||||
timestamp: new Date(2020, 6, 1, 17, 50, 3).toISOString(),
|
||||
},
|
||||
],
|
||||
maturity: 'stable',
|
||||
seenApplications: [],
|
||||
};
|
||||
|
||||
expect(
|
||||
validateSchema('#/components/schemas/featureUsageSchema', data),
|
||||
).toBeUndefined();
|
||||
});
|
45
src/lib/openapi/spec/feature-usage-schema.ts
Normal file
45
src/lib/openapi/spec/feature-usage-schema.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { featureEnvironmentMetricsSchema } from './feature-environment-metrics-schema';
|
||||
|
||||
export const featureUsageSchema = {
|
||||
$id: '#/components/schemas/featureUsageSchema',
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: [
|
||||
'version',
|
||||
'maturity',
|
||||
'featureName',
|
||||
'lastHourUsage',
|
||||
'seenApplications',
|
||||
],
|
||||
properties: {
|
||||
version: {
|
||||
type: 'number',
|
||||
},
|
||||
maturity: {
|
||||
type: 'string',
|
||||
},
|
||||
featureName: {
|
||||
type: 'string',
|
||||
},
|
||||
lastHourUsage: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: '#/components/schemas/featureEnvironmentMetricsSchema',
|
||||
},
|
||||
},
|
||||
seenApplications: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
schemas: {
|
||||
featureEnvironmentMetricsSchema,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export type FeatureUsageSchema = FromSchema<typeof featureUsageSchema>;
|
@ -4,12 +4,34 @@ import { IUnleashConfig } from '../../types/option';
|
||||
import { IUnleashServices } from '../../types';
|
||||
import { Logger } from '../../logger';
|
||||
import ClientMetricsServiceV2 from '../../services/client-metrics/metrics-service-v2';
|
||||
import { NONE } from '../../types/permissions';
|
||||
import { createResponseSchema } from '../../openapi';
|
||||
import { OpenApiService } from '../../services/openapi-service';
|
||||
import { serializeDates } from '../../types/serialize-dates';
|
||||
import {
|
||||
FeatureUsageSchema,
|
||||
featureUsageSchema,
|
||||
} from '../../openapi/spec/feature-usage-schema';
|
||||
import {
|
||||
featureMetricsSchema,
|
||||
FeatureMetricsSchema,
|
||||
} from '../../openapi/spec/feature-metrics-schema';
|
||||
|
||||
interface IName {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface IHoursBack {
|
||||
hoursBack: number;
|
||||
}
|
||||
|
||||
class ClientMetricsController extends Controller {
|
||||
private logger: Logger;
|
||||
|
||||
private metrics: ClientMetricsServiceV2;
|
||||
|
||||
private openApiService: OpenApiService;
|
||||
|
||||
private static HOURS_BACK_MIN = 1;
|
||||
|
||||
private static HOURS_BACK_MAX = 48;
|
||||
@ -18,39 +40,79 @@ class ClientMetricsController extends Controller {
|
||||
config: IUnleashConfig,
|
||||
{
|
||||
clientMetricsServiceV2,
|
||||
}: Pick<IUnleashServices, 'clientMetricsServiceV2'>,
|
||||
openApiService,
|
||||
}: Pick<IUnleashServices, 'clientMetricsServiceV2' | 'openApiService'>,
|
||||
) {
|
||||
super(config);
|
||||
this.logger = config.getLogger('/admin-api/client-metrics.ts');
|
||||
|
||||
this.metrics = clientMetricsServiceV2;
|
||||
this.openApiService = openApiService;
|
||||
|
||||
this.get('/features/:name/raw', this.getRawToggleMetrics);
|
||||
this.get('/features/:name', this.getToggleMetricsSummary);
|
||||
this.route({
|
||||
method: 'get',
|
||||
path: '/features/:name/raw',
|
||||
handler: this.getRawToggleMetrics,
|
||||
permission: NONE,
|
||||
middleware: [
|
||||
openApiService.validPath({
|
||||
operationId: 'getRawFeatureMetrics',
|
||||
tags: ['admin'],
|
||||
responses: {
|
||||
200: createResponseSchema('featureMetricsSchema'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
this.route({
|
||||
method: 'get',
|
||||
path: '/features/:name',
|
||||
handler: this.getToggleMetricsSummary,
|
||||
permission: NONE,
|
||||
middleware: [
|
||||
openApiService.validPath({
|
||||
operationId: 'getFeatureUsageSummary',
|
||||
tags: ['admin'],
|
||||
responses: {
|
||||
200: createResponseSchema('featureUsageSchema'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async getRawToggleMetrics(req: Request, res: Response): Promise<void> {
|
||||
async getRawToggleMetrics(
|
||||
req: Request<any, IName, IHoursBack, any>,
|
||||
res: Response<FeatureMetricsSchema>,
|
||||
): Promise<void> {
|
||||
const { name } = req.params;
|
||||
const { hoursBack } = req.query;
|
||||
const data = await this.metrics.getClientMetricsForToggle(
|
||||
name,
|
||||
this.parseHoursBackQueryParam(hoursBack),
|
||||
);
|
||||
res.json({
|
||||
version: 1,
|
||||
maturity: 'stable',
|
||||
data,
|
||||
});
|
||||
this.openApiService.respondWithValidation(
|
||||
200,
|
||||
res,
|
||||
featureMetricsSchema.$id,
|
||||
{ version: 1, maturity: 'stable', data: serializeDates(data) },
|
||||
);
|
||||
}
|
||||
|
||||
async getToggleMetricsSummary(req: Request, res: Response): Promise<void> {
|
||||
async getToggleMetricsSummary(
|
||||
req: Request<IName>,
|
||||
res: Response<FeatureUsageSchema>,
|
||||
): Promise<void> {
|
||||
const { name } = req.params;
|
||||
const data = await this.metrics.getFeatureToggleMetricsSummary(name);
|
||||
res.json({
|
||||
version: 1,
|
||||
maturity: 'stable',
|
||||
...data,
|
||||
});
|
||||
|
||||
this.openApiService.respondWithValidation(
|
||||
200,
|
||||
res,
|
||||
featureUsageSchema.$id,
|
||||
{ version: 1, maturity: 'stable', ...serializeDates(data) },
|
||||
);
|
||||
}
|
||||
|
||||
private parseHoursBackQueryParam(param: unknown): number | undefined {
|
||||
|
@ -641,6 +641,37 @@ Object {
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"featureEnvironmentMetricsSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
"appName": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"environment": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"featureName": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"no": Object {
|
||||
"type": "number",
|
||||
},
|
||||
"timestamp": Object {
|
||||
"format": "date-time",
|
||||
"type": "string",
|
||||
},
|
||||
"yes": Object {
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"required": Array [
|
||||
"environment",
|
||||
"timestamp",
|
||||
"yes",
|
||||
"no",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
"featureEnvironmentSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
@ -712,6 +743,29 @@ Object {
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
"featureMetricsSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
"data": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/featureEnvironmentMetricsSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"maturity": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"version": Object {
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"required": Array [
|
||||
"version",
|
||||
"maturity",
|
||||
"data",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
"featureSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
@ -892,6 +946,40 @@ Object {
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
"featureUsageSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
"featureName": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"lastHourUsage": Object {
|
||||
"items": Object {
|
||||
"$ref": "#/components/schemas/featureEnvironmentMetricsSchema",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"maturity": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"seenApplications": Object {
|
||||
"items": Object {
|
||||
"type": "string",
|
||||
},
|
||||
"type": "array",
|
||||
},
|
||||
"version": Object {
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"required": Array [
|
||||
"version",
|
||||
"maturity",
|
||||
"featureName",
|
||||
"lastHourUsage",
|
||||
"seenApplications",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
"featureVariantsSchema": Object {
|
||||
"additionalProperties": false,
|
||||
"properties": Object {
|
||||
@ -2436,6 +2524,66 @@ Object {
|
||||
],
|
||||
},
|
||||
},
|
||||
"/api/admin/client-metrics/features/{name}": Object {
|
||||
"get": Object {
|
||||
"operationId": "getFeatureUsageSummary",
|
||||
"parameters": Array [
|
||||
Object {
|
||||
"in": "path",
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"schema": Object {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": Object {
|
||||
"200": Object {
|
||||
"content": Object {
|
||||
"application/json": Object {
|
||||
"schema": Object {
|
||||
"$ref": "#/components/schemas/featureUsageSchema",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "featureUsageSchema",
|
||||
},
|
||||
},
|
||||
"tags": Array [
|
||||
"admin",
|
||||
],
|
||||
},
|
||||
},
|
||||
"/api/admin/client-metrics/features/{name}/raw": Object {
|
||||
"get": Object {
|
||||
"operationId": "getRawFeatureMetrics",
|
||||
"parameters": Array [
|
||||
Object {
|
||||
"in": "path",
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"schema": Object {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": Object {
|
||||
"200": Object {
|
||||
"content": Object {
|
||||
"application/json": Object {
|
||||
"schema": Object {
|
||||
"$ref": "#/components/schemas/featureMetricsSchema",
|
||||
},
|
||||
},
|
||||
},
|
||||
"description": "featureMetricsSchema",
|
||||
},
|
||||
},
|
||||
"tags": Array [
|
||||
"admin",
|
||||
],
|
||||
},
|
||||
},
|
||||
"/api/admin/constraints/validate": Object {
|
||||
"post": Object {
|
||||
"operationId": "validateConstraint",
|
||||
|
Loading…
Reference in New Issue
Block a user