@Override
	public Mono<ClientResponse> filter(ClientRequest originRequest, ExchangeFunction next) {
		EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();

		EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
				.httpHeaders(originRequest.headers())
				.httpMethod(originRequest.method())
				.url(originRequest.url())
				.build();
		enhancedPluginContext.setRequest(enhancedRequestContext);
		enhancedPluginContext.setOriginRequest(originRequest);

		enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
		enhancedPluginContext.setTargetServiceInstance((ServiceInstance) MetadataContextHolder.get()
				.getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE), originRequest.url());

		// Run post enhanced plugins.
		pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
		// request may be changed by plugin
		ClientRequest request = (ClientRequest) enhancedPluginContext.getOriginRequest();
		long startTime = System.currentTimeMillis();
		return next.exchange(request)
				.doOnSuccess(response -> {
					enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);

					EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
							.httpStatus(response.statusCode().value())
							.httpHeaders(response.headers().asHttpHeaders())
							.build();
					enhancedPluginContext.setResponse(enhancedResponseContext);

					// Run post enhanced plugins.
					pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
				})
				.doOnError(t -> {
					enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
					enhancedPluginContext.setThrowable(t);

					// Run exception enhanced plugins.
					pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
				})
				.doFinally(v -> {
					// Run finally enhanced plugins.
					pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
				});
	}
@Test
	public void testRun() throws URISyntaxException {

		doReturn(new URI("http://0.0.0.0/")).when(clientRequest).url();
		doReturn(new HttpHeaders()).when(clientRequest).headers();
		doReturn(HttpMethod.GET).when(clientRequest).method();
		ClientResponse.Headers headers = mock(ClientResponse.Headers.class);
		doReturn(headers).when(clientResponse).headers();
		doReturn(HttpStatusCode.valueOf(200)).when(clientResponse).statusCode();
		doReturn(Mono.just(clientResponse)).when(exchangeFunction).exchange(any());

		EnhancedWebClientExchangeFilterFunction reporter = new EnhancedWebClientExchangeFilterFunction(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
		ClientResponse clientResponse1 = reporter.filter(clientRequest, exchangeFunction).block();
		assertThat(clientResponse1).isEqualTo(clientResponse);

		ClientResponse clientResponse2 = reporter.filter(clientRequest, exchangeFunction).block();
		assertThat(clientResponse2).isEqualTo(clientResponse);

		doReturn(Mono.error(new RuntimeException())).when(exchangeFunction).exchange(any());

		assertThatThrownBy(() -> reporter.filter(clientRequest, exchangeFunction).block()).isInstanceOf(RuntimeException.class);


	}