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