In most cases, endpoints are detected automatically through language agents, service mesh observability solutions, or meter system configurations.
There are some special cases, especially when REST-style URI is used, where the application codes include the parameter in the endpoint name, such as putting order ID in the URI. Examples are /prod/ORDER123
and /prod/ORDER456
. But logically, most would expect to have an endpoint name like prod/{order-id}
. This is a specially designed feature in parameterized endpoint grouping.
If the incoming endpoint name accords with the rules, SkyWalking will group the endpoint by rules.
There are two approaches in which SkyWalking supports endpoint grouping:
Both grouping approaches can work together in sequence.
The OpenAPI definitions are documents based on the OpenAPI Specification (OAS), which is used to define a standard, language-agnostic interface for HTTP APIs.
SkyWalking now supports OAS v2.0+
. It could parse the documents (yaml)
and build grouping rules from them automatically.
Add Specification Extensions
for SkyWalking config in the OpenAPI definition documents; otherwise, all configs are default:
${METHOD}
is a reserved placeholder which represents the HTTP method, e.g. POST/GET...
. ${PATH}
is a reserved placeholder which represents the path, e.g. /products/{id}
.
Extension Name | Required | Description | Default Value |
---|---|---|---|
x-sw-service-name | false | The service name to which these endpoints belong. | The directory name to which the OpenAPI definition documents belong. |
x-sw-endpoint-name-match-rule | false | The rule used to match the endpoint. | ${METHOD}:${PATH} |
x-sw-endpoint-name-format | false | The endpoint name after grouping. | ${METHOD}:${PATH} |
These extensions are under OpenAPI Object
. For example, the document below has a full custom config:
openapi: 3.0.0 x-sw-service-name: serviceB x-sw-endpoint-name-match-rule: "${METHOD}:${PATH}" x-sw-endpoint-name-format: "${METHOD}:${PATH}" info: description: OpenAPI definition for SkyWalking test. version: v2 title: Product API ...
We highly recommend using the default config. The custom config (x-sw-endpoint-name-match-rule/x-sw-endpoint-name-format
) is considered part of the match rules (regex pattern). We have provided some use cases in org.apache.skywalking.oap.server.core.config.group.openapi.EndpointGroupingRuleReader4OpenapiTest
. You may validate your custom config as well.
openapi-definitions
directory, with directories having at most two levels. We recommend using the service name as the subDirectory name, as you will then not be required to set x-sw-service-name
. For example:├── openapi-definitions │ ├── serviceA │ │ ├── customerAPI-v1.yaml │ │ └── productAPI-v1.yaml │ └── serviceB │ └── productAPI-v2.yaml
Core Module
configuration ${SW_CORE_ENABLE_ENDPOINT_NAME_GROUPING_BY_OPENAPI:false}
.We recommend designing the API path as clearly as possible. If the API path is fuzzy and an endpoint name matches multiple paths, SkyWalking would select a path according to the match priority set out below:
/products or /products/inventory
/products/{var1}/{var2} and /products/{var1}/abc
, endpoint name /products/123/abc
will match the second one.1
. E.g. In the case of /products/abc/{var1} and products/{var12345}/ef
, endpoint name /products/abc/ef
will match the first one, because length("abc") = 3
is larger than length("ef") = 2
.If we have an OpenAPI definition doc productAPI-v2.yaml
in directory serviceB
, it will look like this:
openapi: 3.0.0 info: description: OpenAPI definition for SkyWalking test. version: v2 title: Product API tags: - name: product description: product - name: relatedProducts description: Related Products paths: /products: get: tags: - product summary: Get all products list description: Get all products list. operationId: getProducts responses: "200": description: Success content: application/json: schema: type: array items: $ref: "#/components/schemas/Product" /products/{region}/{country}: get: tags: - product summary: Get products regional description: Get products regional with the given id. operationId: getProductRegional parameters: - name: region in: path description: Products region required: true schema: type: string - name: country in: path description: Products country required: true schema: type: string responses: "200": description: successful operation content: application/json: schema: $ref: "#/components/schemas/Product" "400": description: Invalid parameters supplied /products/{id}: get: tags: - product summary: Get product details description: Get product details with the given id. operationId: getProduct parameters: - name: id in: path description: Product id required: true schema: type: integer format: int64 responses: "200": description: successful operation content: application/json: schema: $ref: "#/components/schemas/ProductDetails" "400": description: Invalid product id post: tags: - product summary: Update product details description: Update product details with the given id. operationId: updateProduct parameters: - name: id in: path description: Product id required: true schema: type: integer format: int64 - name: name in: query description: Product name required: true schema: type: string responses: "200": description: successful operation delete: tags: - product summary: Delete product details description: Delete product details with the given id. operationId: deleteProduct parameters: - name: id in: path description: Product id required: true schema: type: integer format: int64 responses: "200": description: successful operation /products/{id}/relatedProducts: get: tags: - relatedProducts summary: Get related products description: Get related products with the given product id. operationId: getRelatedProducts parameters: - name: id in: path description: Product id required: true schema: type: integer format: int64 responses: "200": description: successful operation content: application/json: schema: $ref: "#/components/schemas/RelatedProducts" "400": description: Invalid product id components: schemas: Product: type: object description: Product id and name properties: id: type: integer format: int64 description: Product id name: type: string description: Product name required: - id - name ProductDetails: type: object description: Product details properties: id: type: integer format: int64 description: Product id name: type: string description: Product name description: type: string description: Product description required: - id - name RelatedProducts: type: object description: Related Products properties: id: type: integer format: int32 description: Product id relatedProducts: type: array description: List of related products items: $ref: "#/components/schemas/Product"
Here are some use cases:
Incoming Endpoint | Incoming Service | x-sw-service-name | x-sw-endpoint-name-match-rule | x-sw-endpoint-name-format | Matched | Grouping Result |
---|---|---|---|---|---|---|
GET:/products | serviceB | default | default | default | true | GET:/products |
GET:/products/123 | serviceB | default | default | default | true | GET:/products{id} |
GET:/products/asia/cn | serviceB | default | default | default | true | GET:/products/{region}/{country} |
GET:/products/123/abc/efg | serviceB | default | default | default | false | GET:/products/123/abc/efg |
<GET>:/products/123 | serviceB | default | default | default | false | <GET>:/products/123 |
GET:/products/123 | serviceC | default | default | default | false | GET:/products/123 |
GET:/products/123 | serviceC | serviceC | default | default | true | GET:/products/123 |
<GET>:/products/123 | serviceB | default | <${METHOD}>:${PATH} | <${METHOD}>:${PATH} | true | <GET>:/products/{id} |
GET:/products/123 | serviceB | default | default | ${PATH}:<${METHOD}> | true | /products/{id}:<GET> |
/products/123:<GET> | serviceB | default | ${PATH}:<${METHOD}> | default | true | GET:/products/{id} |
Use Dynamic Configuration to initialize and update OpenAPI definitions, the endpoint grouping rules from OpenAPI will re-create by the new config.
Currently, a user could set up grouping rules through the static YAML file named endpoint-name-grouping.yml
, or use Dynamic Configuration to initialize and update endpoint grouping rules.
Both the static local file and dynamic configuration value share the same YAML format.
grouping: # Endpoint of the service would follow the following rules - service-name: serviceA rules: # Logic name when the regex expression matched. - endpoint-name: /prod/{id} regex: \/prod\/.+