@Override
    public void startHttpUriRecognitionSvr(HttpUriRecognition httpUriRecognitionSvr) {
        if (this.httpUrlRecognitionConfig == null || !httpUriRecognitionSvr.isInitialized()) {
            return;
        }
        this.quickUriGroupingRule = new QuickUriGroupingRule();
        HTTPUrlRecognitionConfig config = this.httpUrlRecognitionConfig;
        Executors.newSingleThreadScheduledExecutor()
            .scheduleWithFixedDelay(
                new RunnableWithExceptionProtection(
                    () -> {
                        int currentExecutionCounter = aiPipelineExecutionCounter.incrementAndGet();
                        if (currentExecutionCounter % config.trainingPeriodHttpUriRecognitionPattern == 0) {
                            // Send the cached URIs to the recognition server to build new patterns.
                            cachedHttpUris.forEach((serviceName, httpUris) -> {
                                final List<HttpUriRecognition.HTTPUri> candidates4UriPatterns = new ArrayList<>(
                                    3000);
                                httpUris.forEach((uri, candidates) -> {
                                    if (candidates.size() == 0) {
                                        //unrecognized uri
                                        candidates4UriPatterns.add(new HttpUriRecognition.HTTPUri(uri));
                                    } else {
                                        String candidateUri;
                                        while ((candidateUri = candidates.poll()) != null) {
                                            candidates4UriPatterns.add(
                                                new HttpUriRecognition.HTTPUri(candidateUri));
                                        }
                                    }
                                });

                                // Reset the cache once the URIs are sent to the recognition server.
                                httpUris.clear();
                                httpUriRecognitionSvr.feedRawData(serviceName, candidates4UriPatterns);
                            });
                        }
                        if (currentExecutionCounter % config.syncPeriodHttpUriRecognitionPattern == 0) {
                            // Sync with the recognition server per 1 min to get the latest patterns.
                            try {
                                config.metadataQueryService.listServices(null, null).forEach(
                                    service -> {
                                        final List<HttpUriPattern> patterns
                                            = httpUriRecognitionSvr.fetchAllPatterns(service.getName());
                                        if (CollectionUtils.isNotEmpty(patterns)) {
                                            patterns.forEach(
                                                p -> quickUriGroupingRule.addRule(
                                                    service.getName(), p.getPattern()));

                                        }
                                    }
                                );
                            } catch (IOException e) {
                                log.error("Fail to load all services.", e);
                            }

                        }
                    },
                    t -> log.error("Fail to recognize URI patterns.", t)
                ), 60, 1, TimeUnit.SECONDS
            );

    }
Format the endpoint name according to the API patterns.

@param serviceName  service name
@param endpointName endpoint name to be formatted.
@return Tuple2 The result of endpoint name formatting.
The first element is the formatted name or original name when not formatted.
The second element is a boolean represented the endpoint name is formatted or not.
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/group/EndpointNameGrouping.java