使用 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" });