使用 OnRequestCompleted 记录
编辑使用 OnRequestCompleted 记录编辑
在构造要传递给客户端的连接设置时,您可以将类型为 Action<IApiCallDetails>
的回调传递给 OnRequestCompleted
方法,该方法可以在每次收到响应(好的或坏的)时进行监听。
如果您有复杂的日志记录需求,这是一个添加它的好地方,因为您可以访问请求和响应详细信息。
在此示例中,我们将在连接设置上使用 OnRequestCompleted
,以便在每次调用它时增加一个计数器。
var counter = 0; var client = new ElasticClient(new AlwaysInMemoryConnectionSettings().OnRequestCompleted(r => counter++)); client.RootNodeInfo(); counter.Should().Be(1); await client.RootNodeInfoAsync(); counter.Should().Be(2);
即使抛出异常也会调用 OnRequestCompleted
,因此即使客户端配置为抛出异常也可以使用它
var counter = 0; var client = FixedResponseClient.Create( new { }, 500, connectionSettings => connectionSettings .ThrowExceptions() .OnRequestCompleted(r => counter++) ); Assert.Throws<TransportException>(() => client.RootNodeInfo()); counter.Should().Be(1); await Assert.ThrowsAsync<TransportException>(async () => await client.RootNodeInfoAsync()); counter.Should().Be(2);
这是一个使用 OnRequestCompleted()
进行更复杂日志记录的示例
默认情况下,客户端直接写入请求流并直接从响应流反序列化。
如果您还想捕获请求和/或响应字节,则还需要将 .DisableDirectStreaming()
设置为 true
。
var list = new List<string>(); var connectionPool = new SingleNodeConnectionPool(new Uri("https://127.0.0.1:9200")); var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) .DefaultIndex("default-index") .DisableDirectStreaming() .OnRequestCompleted(apiCallDetails => { // log out the request and the request body, if one exists for the type of request if (apiCallDetails.RequestBodyInBytes != null) { list.Add( $"{apiCallDetails.HttpMethod} {apiCallDetails.Uri} " + $"{Encoding.UTF8.GetString(apiCallDetails.RequestBodyInBytes)}"); } else { list.Add($"{apiCallDetails.HttpMethod} {apiCallDetails.Uri}"); } // log out the response and the response body, if one exists for the type of response if (apiCallDetails.ResponseBodyInBytes != null) { list.Add($"Status: {apiCallDetails.HttpStatusCode}" + $"{Encoding.UTF8.GetString(apiCallDetails.ResponseBodyInBytes)}"); } else { list.Add($"Status: {apiCallDetails.HttpStatusCode}"); } }); var client = new ElasticClient(settings); var syncResponse = client.Search<object>(s => s .AllIndices() .Scroll("2m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); list.Count.Should().Be(2); var asyncResponse = await client.SearchAsync<object>(s => s .AllIndices() .Scroll("10m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); list.Count.Should().Be(4); list.Should().BeEquivalentTo(new[] { @"POST https://127.0.0.1:9200/_all/_search?typed_keys=true&scroll=2m {""sort"":[{""_doc"":{""order"":""asc""}}]}", @"Status: 200", @"POST https://127.0.0.1:9200/_all/_search?typed_keys=true&scroll=10m {""sort"":[{""_doc"":{""order"":""asc""}}]}", @"Status: 200" });
这里我们使用 |
|
禁用直接流式传输,以便我们可以捕获请求和响应字节 |
|
请求完成后执行某些操作。在这里,我们只是添加到列表中,但在您的应用程序中,您可能正在记录到文件。 |
|
进行同步调用 |
|
进行异步调用 |
|
断言列表包含写入传递给 |
在生产环境中运行应用程序时,您可能不希望对*所有*请求禁用直接流式传输,因为这样做会导致性能开销,因为需要在内存中缓冲请求和响应字节。但是,以临时方式捕获请求和响应可能很有用,例如在生产环境中排查问题。
为此,可以针对*每个请求*启用 DisableDirectStreaming
。在使用此功能时,可以在 OnRequestCompleted
中配置通用日志记录机制,并仅在必要时记录请求和响应
var list = new List<string>(); var connectionPool = new SingleNodeConnectionPool(new Uri("https://127.0.0.1:9200")); var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) .DefaultIndex("default-index") .OnRequestCompleted(apiCallDetails => { // log out the request and the request body, if one exists for the type of request if (apiCallDetails.RequestBodyInBytes != null) { list.Add( $"{apiCallDetails.HttpMethod} {apiCallDetails.Uri} " + $"{Encoding.UTF8.GetString(apiCallDetails.RequestBodyInBytes)}"); } else { list.Add($"{apiCallDetails.HttpMethod} {apiCallDetails.Uri}"); } // log out the response and the response body, if one exists for the type of response if (apiCallDetails.ResponseBodyInBytes != null) { list.Add($"Status: {apiCallDetails.HttpStatusCode}" + $"{Encoding.UTF8.GetString(apiCallDetails.ResponseBodyInBytes)}"); } else { list.Add($"Status: {apiCallDetails.HttpStatusCode}"); } }); var client = new ElasticClient(settings); var syncResponse = client.Search<object>(s => s .AllIndices() .Scroll("2m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); list.Count.Should().Be(2); var asyncResponse = await client.SearchAsync<object>(s => s .RequestConfiguration(r => r .DisableDirectStreaming() ) .AllIndices() .Scroll("10m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); list.Count.Should().Be(4); list.Should().BeEquivalentTo(new[] { @"POST https://127.0.0.1:9200/_all/_search?typed_keys=true&scroll=2m", @"Status: 200", @"POST https://127.0.0.1:9200/_all/_search?typed_keys=true&scroll=10m {""sort"":[{""_doc"":{""order"":""asc""}}]}", @"Status: 200" });