Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HTTP/OAS] Added response schemas for /api/status #181277

Merged

Conversation

jloleysens
Copy link
Contributor

@jloleysens jloleysens commented Apr 22, 2024

Summary

Part #180056. Adds new response schemas to the /api/status endpoint for the purposes of OAS generation.

How to test

  1. Start ES
  2. Add server.oas.enabled: true to kibana.dev.yml
  3. Start Kibana yarn start --no-base-path
  4. curl -s -uelastic:changeme http://localhost:5601/api/oas\?pathStartsWith\=/api/status | jq
output
{
  "openapi": "3.0.0",
  "info": {
    "title": "Kibana HTTP APIs",
    "version": "0.0.0"
  },
  "servers": [
    {
      "url": "http://localhost:5601"
    }
  ],
  "paths": {
    "/api/status": {
      "get": {
        "summary": "Get Kibana's current status.",
        "responses": {
          "200": {
            "description": "Get Kibana's current status.",
            "content": {
              "application/json; Elastic-Api-Version=2023-10-31": {
                "schema": {
                  "description": "Kibana's operational status. A minimal response is sent for unauthorized users.",
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/core.status.response"
                    },
                    {
                      "$ref": "#/components/schemas/core.status.redactedResponse"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Get Kibana's current status.",
            "content": {
              "application/json; Elastic-Api-Version=2023-10-31": {
                "schema": {
                  "description": "Kibana's operational status. A minimal response is sent for unauthorized users.",
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/core.status.response"
                    },
                    {
                      "$ref": "#/components/schemas/core.status.redactedResponse"
                    }
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "elastic-api-version",
            "description": "The version of the API to use",
            "schema": {
              "type": "string",
              "enum": [
                "2023-10-31"
              ],
              "default": "2023-10-31"
            }
          },
          {
            "name": "v7format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Set to \"true\" to get the response in v7 format."
          },
          {
            "name": "v8format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Set to \"true\" to get the response in v8 format."
          }
        ],
        "operationId": "/api/status#0"
      }
    }
  },
  "components": {
    "schemas": {
      "core.status.response": {
        "description": "Kibana's operational status as well as a detailed breakdown of plugin statuses indication of various loads (like event loop utilization and network traffic) at time of request.",
        "type": "object",
        "properties": {
          "name": {
            "description": "Kibana instance name.",
            "type": "string"
          },
          "uuid": {
            "description": "Unique, generated Kibana instance UUID. This UUID should persist even if the Kibana process restarts.",
            "type": "string"
          },
          "version": {
            "type": "object",
            "properties": {
              "number": {
                "description": "A semantic version number.",
                "type": "string"
              },
              "build_hash": {
                "description": "A unique hash value representing the git commit of this Kibana build.",
                "type": "string"
              },
              "build_number": {
                "description": "A monotonically increasing number, each subsequent build will have a higher number.",
                "type": "number"
              },
              "build_snapshot": {
                "description": "Whether this build is a snapshot build.",
                "type": "boolean"
              },
              "build_flavor": {
                "description": "The build flavour determines configuration and behavior of Kibana. On premise users will almost always run the \"traditional\" flavour, while other flavours are reserved for Elastic-specific use cases.",
                "anyOf": [
                  {
                    "enum": [
                      "serverless"
                    ],
                    "type": "string"
                  },
                  {
                    "enum": [
                      "traditional"
                    ],
                    "type": "string"
                  }
                ]
              },
              "build_date": {
                "description": "The date and time of this build.",
                "type": "string"
              }
            },
            "additionalProperties": false,
            "required": [
              "number",
              "build_hash",
              "build_number",
              "build_snapshot",
              "build_flavor",
              "build_date"
            ]
          },
          "status": {
            "type": "object",
            "properties": {
              "overall": {
                "type": "object",
                "properties": {
                  "level": {
                    "description": "Service status levels as human and machine readable values.",
                    "anyOf": [
                      {
                        "enum": [
                          "available"
                        ],
                        "type": "string"
                      },
                      {
                        "enum": [
                          "degraded"
                        ],
                        "type": "string"
                      },
                      {
                        "enum": [
                          "unavailable"
                        ],
                        "type": "string"
                      },
                      {
                        "enum": [
                          "critical"
                        ],
                        "type": "string"
                      }
                    ]
                  },
                  "summary": {
                    "description": "A human readable summary of the service status.",
                    "type": "string"
                  },
                  "detail": {
                    "description": "Human readable detail of the service status.",
                    "type": "string"
                  },
                  "documentationUrl": {
                    "description": "A URL to further documentation regarding this service.",
                    "type": "string"
                  },
                  "meta": {
                    "description": "An unstructured set of extra metadata about this service.",
                    "type": "object",
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false,
                "required": [
                  "level",
                  "summary",
                  "meta"
                ]
              },
              "core": {
                "description": "Statuses of core Kibana services.",
                "type": "object",
                "properties": {
                  "elasticsearch": {
                    "type": "object",
                    "properties": {
                      "level": {
                        "description": "Service status levels as human and machine readable values.",
                        "anyOf": [
                          {
                            "enum": [
                              "available"
                            ],
                            "type": "string"
                          },
                          {
                            "enum": [
                              "degraded"
                            ],
                            "type": "string"
                          },
                          {
                            "enum": [
                              "unavailable"
                            ],
                            "type": "string"
                          },
                          {
                            "enum": [
                              "critical"
                            ],
                            "type": "string"
                          }
                        ]
                      },
                      "summary": {
                        "description": "A human readable summary of the service status.",
                        "type": "string"
                      },
                      "detail": {
                        "description": "Human readable detail of the service status.",
                        "type": "string"
                      },
                      "documentationUrl": {
                        "description": "A URL to further documentation regarding this service.",
                        "type": "string"
                      },
                      "meta": {
                        "description": "An unstructured set of extra metadata about this service.",
                        "type": "object",
                        "additionalProperties": {}
                      }
                    },
                    "additionalProperties": false,
                    "required": [
                      "level",
                      "summary",
                      "meta"
                    ]
                  },
                  "savedObjects": {
                    "type": "object",
                    "properties": {
                      "level": {
                        "description": "Service status levels as human and machine readable values.",
                        "anyOf": [
                          {
                            "enum": [
                              "available"
                            ],
                            "type": "string"
                          },
                          {
                            "enum": [
                              "degraded"
                            ],
                            "type": "string"
                          },
                          {
                            "enum": [
                              "unavailable"
                            ],
                            "type": "string"
                          },
                          {
                            "enum": [
                              "critical"
                            ],
                            "type": "string"
                          }
                        ]
                      },
                      "summary": {
                        "description": "A human readable summary of the service status.",
                        "type": "string"
                      },
                      "detail": {
                        "description": "Human readable detail of the service status.",
                        "type": "string"
                      },
                      "documentationUrl": {
                        "description": "A URL to further documentation regarding this service.",
                        "type": "string"
                      },
                      "meta": {
                        "description": "An unstructured set of extra metadata about this service.",
                        "type": "object",
                        "additionalProperties": {}
                      }
                    },
                    "additionalProperties": false,
                    "required": [
                      "level",
                      "summary",
                      "meta"
                    ]
                  }
                },
                "additionalProperties": false,
                "required": [
                  "elasticsearch",
                  "savedObjects"
                ]
              },
              "plugins": {
                "description": "A dynamic mapping of plugin ID to plugin status.",
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "level": {
                      "description": "Service status levels as human and machine readable values.",
                      "anyOf": [
                        {
                          "enum": [
                            "available"
                          ],
                          "type": "string"
                        },
                        {
                          "enum": [
                            "degraded"
                          ],
                          "type": "string"
                        },
                        {
                          "enum": [
                            "unavailable"
                          ],
                          "type": "string"
                        },
                        {
                          "enum": [
                            "critical"
                          ],
                          "type": "string"
                        }
                      ]
                    },
                    "summary": {
                      "description": "A human readable summary of the service status.",
                      "type": "string"
                    },
                    "detail": {
                      "description": "Human readable detail of the service status.",
                      "type": "string"
                    },
                    "documentationUrl": {
                      "description": "A URL to further documentation regarding this service.",
                      "type": "string"
                    },
                    "meta": {
                      "description": "An unstructured set of extra metadata about this service.",
                      "type": "object",
                      "additionalProperties": {}
                    }
                  },
                  "additionalProperties": false,
                  "required": [
                    "level",
                    "summary",
                    "meta"
                  ]
                }
              }
            },
            "additionalProperties": false,
            "required": [
              "overall",
              "core",
              "plugins"
            ]
          },
          "metrics": {
            "description": "Metric groups collected by Kibana.",
            "type": "object",
            "properties": {
              "elasticsearch_client": {
                "description": "Current network metrics of Kibana's Elasticsearch client.",
                "type": "object",
                "properties": {
                  "totalActiveSockets": {
                    "description": "Count of network sockets currently in use.",
                    "type": "number"
                  },
                  "totalIdleSockets": {
                    "description": "Count of network sockets currently idle.",
                    "type": "number"
                  },
                  "totalQueuedRequests": {
                    "description": "Count of requests not yet assigned to sockets.",
                    "type": "number"
                  }
                },
                "additionalProperties": false,
                "required": [
                  "totalActiveSockets",
                  "totalIdleSockets",
                  "totalQueuedRequests"
                ]
              },
              "last_updated": {
                "description": "The time metrics were collected.",
                "type": "string"
              },
              "collection_interval_in_millis": {
                "description": "The interval at which metrics should be collected.",
                "type": "number"
              }
            },
            "additionalProperties": false,
            "required": [
              "elasticsearch_client",
              "last_updated",
              "collection_interval_in_millis"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "name",
          "uuid",
          "version",
          "status",
          "metrics"
        ]
      },
      "core.status.redactedResponse": {
        "description": "A minimal representation of Kibana's operational status.",
        "type": "object",
        "properties": {
          "status": {
            "type": "object",
            "properties": {
              "overall": {
                "type": "object",
                "properties": {
                  "level": {
                    "description": "Service status levels as human and machine readable values.",
                    "anyOf": [
                      {
                        "enum": [
                          "available"
                        ],
                        "type": "string"
                      },
                      {
                        "enum": [
                          "degraded"
                        ],
                        "type": "string"
                      },
                      {
                        "enum": [
                          "unavailable"
                        ],
                        "type": "string"
                      },
                      {
                        "enum": [
                          "critical"
                        ],
                        "type": "string"
                      }
                    ]
                  }
                },
                "additionalProperties": false,
                "required": [
                  "level"
                ]
              }
            },
            "additionalProperties": false,
            "required": [
              "overall"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "status"
        ]
      }
    },
    "securitySchemes": {
      "basicAuth": {
        "type": "http",
        "scheme": "basic"
      },
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization"
      }
    }
  },
  "security": [
    {
      "basicAuth": []
    }
  ]
}

Related to #181622

Notes

@jloleysens
Copy link
Contributor Author

/ci

@jloleysens
Copy link
Contributor Author

/ci

@jloleysens jloleysens marked this pull request as ready for review April 22, 2024 14:48
@jloleysens jloleysens requested a review from a team as a code owner April 22, 2024 14:48
@jloleysens jloleysens added Feature:http Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc release_note:skip Skip the PR/issue when compiling release notes v8.14.0 labels Apr 22, 2024
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-core (Team:Core)

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving as it's technically LGTM

@jloleysens jloleysens changed the title [HTTP] Added response schemas for /api/status [HTTP/OAS] Added response schemas for /api/status Apr 25, 2024
jloleysens added a commit that referenced this pull request Apr 29, 2024
## Summary

Based on the introduction of new response schemas for OAS generation we
are going to start the long tail of introducing missing response (`joi`)
schemas. We have roughly 520 known public APIs, most of which do not
have response schemas defined. We expected a fairly large increase in
`@kbn/config-schema` definitions in the coming weeks/months. Regardless
of actual outcome and given how slow schema instantiation is, this
presents a slight concern for startup time.

## Proposed changes

Give consumers guidance and a way to pass in validation lazily. Under
the hood we make sure that the lazy schemas only get called once.

```ts

/**
 * A validation schema factory.
 *
 * @note Used to lazily create schemas that are otherwise not needed
 * @note Assume this function will only be called once
 *
 * @return A @kbn/config-schema schema
 * @public
 */
export type LazyValidator = () => Type<unknown>;

/** @public */
export interface VersionedRouteCustomResponseBodyValidation {
  /** A custom validation function */
  custom: RouteValidationFunction<unknown>;
}

/** @public */
export type VersionedResponseBodyValidation =
  | LazyValidator
  | VersionedRouteCustomResponseBodyValidation;

/**
 * Map of response status codes to response schemas
 *
 * @note Instantiating response schemas is expensive, especially when it is
 *       not needed in most cases. See example below to ensure this is lazily
 *       provided.
 *
 * @note The {@link TypeOf} type utility from @kbn/config-schema can extract
 *       types from lazily created schemas
 *
 * @example
 * ```ts
 * // Avoid this:
 * const badResponseSchema = schema.object({ foo: foo.string() });
 * // Do this:
 * const goodResponseSchema = () => schema.object({ foo: foo.string() });
 *
 * type ResponseType = TypeOf<typeof goodResponseSchema>;
 * ...
 * .addVersion(
 *  { ... validation: { response: { 200: { body: goodResponseSchema } } } },
 *  handlerFn
 * )
 * ...
 * ```
 * @public
 */
export interface VersionedRouteResponseValidation {
  [statusCode: number]: {
    body: VersionedResponseBodyValidation;
  };
  unsafe?: { body?: boolean };
}
```

## Notes

* Expected (worst case) in low resource environments is an additional
1.5 seconds to start up time and additional ~70MB to memory pressure
which is not a great trade-off for functionality that is only used when
OAS generation is on.

Related #181277
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Apr 29, 2024
## Summary

Based on the introduction of new response schemas for OAS generation we
are going to start the long tail of introducing missing response (`joi`)
schemas. We have roughly 520 known public APIs, most of which do not
have response schemas defined. We expected a fairly large increase in
`@kbn/config-schema` definitions in the coming weeks/months. Regardless
of actual outcome and given how slow schema instantiation is, this
presents a slight concern for startup time.

## Proposed changes

Give consumers guidance and a way to pass in validation lazily. Under
the hood we make sure that the lazy schemas only get called once.

```ts

/**
 * A validation schema factory.
 *
 * @note Used to lazily create schemas that are otherwise not needed
 * @note Assume this function will only be called once
 *
 * @return A @kbn/config-schema schema
 * @public
 */
export type LazyValidator = () => Type<unknown>;

/** @public */
export interface VersionedRouteCustomResponseBodyValidation {
  /** A custom validation function */
  custom: RouteValidationFunction<unknown>;
}

/** @public */
export type VersionedResponseBodyValidation =
  | LazyValidator
  | VersionedRouteCustomResponseBodyValidation;

/**
 * Map of response status codes to response schemas
 *
 * @note Instantiating response schemas is expensive, especially when it is
 *       not needed in most cases. See example below to ensure this is lazily
 *       provided.
 *
 * @note The {@link TypeOf} type utility from @kbn/config-schema can extract
 *       types from lazily created schemas
 *
 * @example
 * ```ts
 * // Avoid this:
 * const badResponseSchema = schema.object({ foo: foo.string() });
 * // Do this:
 * const goodResponseSchema = () => schema.object({ foo: foo.string() });
 *
 * type ResponseType = TypeOf<typeof goodResponseSchema>;
 * ...
 * .addVersion(
 *  { ... validation: { response: { 200: { body: goodResponseSchema } } } },
 *  handlerFn
 * )
 * ...
 * ```
 * @public
 */
export interface VersionedRouteResponseValidation {
  [statusCode: number]: {
    body: VersionedResponseBodyValidation;
  };
  unsafe?: { body?: boolean };
}
```

## Notes

* Expected (worst case) in low resource environments is an additional
1.5 seconds to start up time and additional ~70MB to memory pressure
which is not a great trade-off for functionality that is only used when
OAS generation is on.

Related elastic#181277

(cherry picked from commit 97e1d9f)
kibanamachine referenced this pull request Apr 29, 2024
# Backport

This will backport the following commits from `main` to `8.14`:
- [[HTTP/OAS] Lazy response schemas
(#181622)](#181622)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Jean-Louis
Leysens","email":"jeanlouis.leysens@elastic.co"},"sourceCommit":{"committedDate":"2024-04-29T09:22:44Z","message":"[HTTP/OAS]
Lazy response schemas (#181622)\n\n## Summary\r\n\r\nBased on the
introduction of new response schemas for OAS generation we\r\nare going
to start the long tail of introducing missing response
(`joi`)\r\nschemas. We have roughly 520 known public APIs, most of which
do not\r\nhave response schemas defined. We expected a fairly large
increase in\r\n`@kbn/config-schema` definitions in the coming
weeks/months. Regardless\r\nof actual outcome and given how slow schema
instantiation is, this\r\npresents a slight concern for startup
time.\r\n\r\n## Proposed changes\r\n\r\nGive consumers guidance and a
way to pass in validation lazily. Under\r\nthe hood we make sure that
the lazy schemas only get called once.\r\n\r\n```ts\r\n\r\n/**\r\n * A
validation schema factory.\r\n *\r\n * @note Used to lazily create
schemas that are otherwise not needed\r\n * @note Assume this function
will only be called once\r\n *\r\n * @return A @kbn/config-schema
schema\r\n * @public\r\n */\r\nexport type LazyValidator = () =>
Type<unknown>;\r\n\r\n/** @public */\r\nexport interface
VersionedRouteCustomResponseBodyValidation {\r\n /** A custom validation
function */\r\n custom:
RouteValidationFunction<unknown>;\r\n}\r\n\r\n/** @public */\r\nexport
type VersionedResponseBodyValidation =\r\n | LazyValidator\r\n |
VersionedRouteCustomResponseBodyValidation;\r\n\r\n/**\r\n * Map of
response status codes to response schemas\r\n *\r\n * @note
Instantiating response schemas is expensive, especially when it is\r\n *
not needed in most cases. See example below to ensure this is lazily\r\n
* provided.\r\n *\r\n * @note The {@link TypeOf} type utility from
@kbn/config-schema can extract\r\n * types from lazily created
schemas\r\n *\r\n * @example\r\n * ```ts\r\n * // Avoid this:\r\n *
const badResponseSchema = schema.object({ foo: foo.string() });\r\n * //
Do this:\r\n * const goodResponseSchema = () => schema.object({ foo:
foo.string() });\r\n *\r\n * type ResponseType = TypeOf<typeof
goodResponseSchema>;\r\n * ...\r\n * .addVersion(\r\n * { ...
validation: { response: { 200: { body: goodResponseSchema } } } },\r\n *
handlerFn\r\n * )\r\n * ...\r\n * ```\r\n * @public\r\n */\r\nexport
interface VersionedRouteResponseValidation {\r\n [statusCode: number]:
{\r\n body: VersionedResponseBodyValidation;\r\n };\r\n unsafe?: {
body?: boolean };\r\n}\r\n```\r\n\r\n## Notes\r\n\r\n* Expected (worst
case) in low resource environments is an additional\r\n1.5 seconds to
start up time and additional ~70MB to memory pressure\r\nwhich is not a
great trade-off for functionality that is only used when\r\nOAS
generation is on.\r\n\r\nRelated
https://github.com/elastic/kibana/pull/181277","sha":"97e1d9f4b8b816d45b31a9caa0feca9bbb9c3bd8","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:http","Team:Core","release_note:skip","ci:project-deploy-observability","v8.14.0","v8.15.0"],"title":"[HTTP/OAS]
Lazy response
schemas","number":181622,"url":"https://github.com/elastic/kibana/pull/181622","mergeCommit":{"message":"[HTTP/OAS]
Lazy response schemas (#181622)\n\n## Summary\r\n\r\nBased on the
introduction of new response schemas for OAS generation we\r\nare going
to start the long tail of introducing missing response
(`joi`)\r\nschemas. We have roughly 520 known public APIs, most of which
do not\r\nhave response schemas defined. We expected a fairly large
increase in\r\n`@kbn/config-schema` definitions in the coming
weeks/months. Regardless\r\nof actual outcome and given how slow schema
instantiation is, this\r\npresents a slight concern for startup
time.\r\n\r\n## Proposed changes\r\n\r\nGive consumers guidance and a
way to pass in validation lazily. Under\r\nthe hood we make sure that
the lazy schemas only get called once.\r\n\r\n```ts\r\n\r\n/**\r\n * A
validation schema factory.\r\n *\r\n * @note Used to lazily create
schemas that are otherwise not needed\r\n * @note Assume this function
will only be called once\r\n *\r\n * @return A @kbn/config-schema
schema\r\n * @public\r\n */\r\nexport type LazyValidator = () =>
Type<unknown>;\r\n\r\n/** @public */\r\nexport interface
VersionedRouteCustomResponseBodyValidation {\r\n /** A custom validation
function */\r\n custom:
RouteValidationFunction<unknown>;\r\n}\r\n\r\n/** @public */\r\nexport
type VersionedResponseBodyValidation =\r\n | LazyValidator\r\n |
VersionedRouteCustomResponseBodyValidation;\r\n\r\n/**\r\n * Map of
response status codes to response schemas\r\n *\r\n * @note
Instantiating response schemas is expensive, especially when it is\r\n *
not needed in most cases. See example below to ensure this is lazily\r\n
* provided.\r\n *\r\n * @note The {@link TypeOf} type utility from
@kbn/config-schema can extract\r\n * types from lazily created
schemas\r\n *\r\n * @example\r\n * ```ts\r\n * // Avoid this:\r\n *
const badResponseSchema = schema.object({ foo: foo.string() });\r\n * //
Do this:\r\n * const goodResponseSchema = () => schema.object({ foo:
foo.string() });\r\n *\r\n * type ResponseType = TypeOf<typeof
goodResponseSchema>;\r\n * ...\r\n * .addVersion(\r\n * { ...
validation: { response: { 200: { body: goodResponseSchema } } } },\r\n *
handlerFn\r\n * )\r\n * ...\r\n * ```\r\n * @public\r\n */\r\nexport
interface VersionedRouteResponseValidation {\r\n [statusCode: number]:
{\r\n body: VersionedResponseBodyValidation;\r\n };\r\n unsafe?: {
body?: boolean };\r\n}\r\n```\r\n\r\n## Notes\r\n\r\n* Expected (worst
case) in low resource environments is an additional\r\n1.5 seconds to
start up time and additional ~70MB to memory pressure\r\nwhich is not a
great trade-off for functionality that is only used when\r\nOAS
generation is on.\r\n\r\nRelated
https://github.com/elastic/kibana/pull/181277","sha":"97e1d9f4b8b816d45b31a9caa0feca9bbb9c3bd8"}},"sourceBranch":"main","suggestedTargetBranches":["8.14"],"targetPullRequestStates":[{"branch":"8.14","label":"v8.14.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.15.0","branchLabelMappingKey":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/181622","number":181622,"mergeCommit":{"message":"[HTTP/OAS]
Lazy response schemas (#181622)\n\n## Summary\r\n\r\nBased on the
introduction of new response schemas for OAS generation we\r\nare going
to start the long tail of introducing missing response
(`joi`)\r\nschemas. We have roughly 520 known public APIs, most of which
do not\r\nhave response schemas defined. We expected a fairly large
increase in\r\n`@kbn/config-schema` definitions in the coming
weeks/months. Regardless\r\nof actual outcome and given how slow schema
instantiation is, this\r\npresents a slight concern for startup
time.\r\n\r\n## Proposed changes\r\n\r\nGive consumers guidance and a
way to pass in validation lazily. Under\r\nthe hood we make sure that
the lazy schemas only get called once.\r\n\r\n```ts\r\n\r\n/**\r\n * A
validation schema factory.\r\n *\r\n * @note Used to lazily create
schemas that are otherwise not needed\r\n * @note Assume this function
will only be called once\r\n *\r\n * @return A @kbn/config-schema
schema\r\n * @public\r\n */\r\nexport type LazyValidator = () =>
Type<unknown>;\r\n\r\n/** @public */\r\nexport interface
VersionedRouteCustomResponseBodyValidation {\r\n /** A custom validation
function */\r\n custom:
RouteValidationFunction<unknown>;\r\n}\r\n\r\n/** @public */\r\nexport
type VersionedResponseBodyValidation =\r\n | LazyValidator\r\n |
VersionedRouteCustomResponseBodyValidation;\r\n\r\n/**\r\n * Map of
response status codes to response schemas\r\n *\r\n * @note
Instantiating response schemas is expensive, especially when it is\r\n *
not needed in most cases. See example below to ensure this is lazily\r\n
* provided.\r\n *\r\n * @note The {@link TypeOf} type utility from
@kbn/config-schema can extract\r\n * types from lazily created
schemas\r\n *\r\n * @example\r\n * ```ts\r\n * // Avoid this:\r\n *
const badResponseSchema = schema.object({ foo: foo.string() });\r\n * //
Do this:\r\n * const goodResponseSchema = () => schema.object({ foo:
foo.string() });\r\n *\r\n * type ResponseType = TypeOf<typeof
goodResponseSchema>;\r\n * ...\r\n * .addVersion(\r\n * { ...
validation: { response: { 200: { body: goodResponseSchema } } } },\r\n *
handlerFn\r\n * )\r\n * ...\r\n * ```\r\n * @public\r\n */\r\nexport
interface VersionedRouteResponseValidation {\r\n [statusCode: number]:
{\r\n body: VersionedResponseBodyValidation;\r\n };\r\n unsafe?: {
body?: boolean };\r\n}\r\n```\r\n\r\n## Notes\r\n\r\n* Expected (worst
case) in low resource environments is an additional\r\n1.5 seconds to
start up time and additional ~70MB to memory pressure\r\nwhich is not a
great trade-off for functionality that is only used when\r\nOAS
generation is on.\r\n\r\nRelated
https://github.com/elastic/kibana/pull/181277","sha":"97e1d9f4b8b816d45b31a9caa0feca9bbb9c3bd8"}}]}]
BACKPORT-->

Co-authored-by: Jean-Louis Leysens <jeanlouis.leysens@elastic.co>
@jloleysens jloleysens merged commit 1e80b01 into elastic:main May 7, 2024
35 checks passed
@jloleysens jloleysens deleted the http/added-response-schema-for-status branch May 7, 2024 08:28
@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.14 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 181277

Questions ?

Please refer to the Backport tool documentation

@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add the label auto-backport or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 181277 locally

@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Aug 18, 2024
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add the label auto-backport or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 181277 locally

@jbudz jbudz added the backport:skip This commit does not require backporting label Sep 30, 2024
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:http release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v8.14.0 v8.15.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants