为什么我的 Polly 重试策略中的 OperationKey 为空?
Why is OperationKey empty in my Polly retry policy?
我使用的是 Polly 版本 7.1.1
我有一个简单的 Polly 重试策略,它会在操作失败时重试一次 NpgsqlException
:
var policy = Policy
.Handle<NpgsqlException>()
.Retry(
retryCount: 1,
onRetry: (exception, retryCount, context) =>
{
_logger.Log(LogLevel.Warning, $"Retry {retryCount} of {context.OperationKey}, due to {exception.Message}", exception);
})
.WithPolicyKey("PostgresConnectionPolicy");
我有一个尝试连接到 PostgreSQL 数据库的方法和 运行 使用上述策略的查询:
using (var conn = new NpgsqlConnection("myConnectionString"))
{
conn.Open()
using(var command = GetCommand())
{
policy.Execute(
action: context => command.ExecuteNonQuery(),
contextData: new Context("Command.ExecuteNonQuery"));
}
}
该方法失败,重试,记录器打印以下内容:
Retry 1 of , due to 42P01: relation "myDatabase" does not exist
我希望记录以下内容:
Retry 1 of Command.ExecuteNonQuery, due to 42P01: relation "myDatabase" does not exist
为什么策略记录重试时 OperationKey
为空?
编辑: 添加一个简化的控制台应用程序作为示例。
这会将以下内容打印到控制台:
Retry 1 of , due to Testing Polly
Error.
示例:
using Polly;
using System;
namespace TestPolly
{
class Program
{
static void Main(string[] args)
{
var policy = Policy
.Handle<Exception>()
.Retry(
retryCount: 1,
onRetry: (exception, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} of {context.OperationKey}, due to {exception.Message}");
})
.WithPolicyKey("PostgresConnectionPolicy");
try
{
policy.Execute(
action: context => TestPolly(),
contextData: new Context("TestPolly"));
}
catch (Exception e)
{
Console.WriteLine("Error.");
}
Console.ReadKey();
}
private static void TestPolly()
{
throw new Exception("Testing Polly");
}
}
}
改用自定义上下文解决了这个问题。
政策:
var policy = Policy
.Handle<NpgsqlException>()
.Retry(
retryCount: 1,
onRetry: (exception, retryCount, context) =>
{
_logger.Log(LogLevel.Warning, $"Retry {retryCount} of {context["Operation"]}, due to {exception.Message}", exception);
})
.WithPolicyKey("PostgresConnectionPolicy");
执行:
policy.Execute(
action: context => command.ExecuteNonQuery(),
contextData: new Context() { { "Operation", "Command.ExecuteNonQuery()" } });
上下文对象
- 定义了一些predefined fields(如
OperationKey
、PolicyKey
、CorrelationId
)
- 它 implements
IDictionary<string, object>
界面让消费者提供任何 key-value 对。
如果您查看 this line of the source code or the documentation,您会发现有一个构造函数重载接受 OperationKey
.
因此,您可以这样定义执行调用:
policy.Execute(
action: context => command.ExecuteNonQuery(),
contextData: new Context("Command.ExecuteNonQuery()"));
我认为这是一种更好的方法,因为您不依赖 string-based 密钥插入和检索。
更新:我发现了问题。
您一直在使用错误的重载 Execute
。
policy.Execute(
action: context => command.ExecuteNonQuery(),
context: new Context("Command.ExecuteNonQuery()"));
使用 context
而不是 contextData
并且 OperationKey
将会出现。
我使用的是 Polly 版本 7.1.1
我有一个简单的 Polly 重试策略,它会在操作失败时重试一次 NpgsqlException
:
var policy = Policy
.Handle<NpgsqlException>()
.Retry(
retryCount: 1,
onRetry: (exception, retryCount, context) =>
{
_logger.Log(LogLevel.Warning, $"Retry {retryCount} of {context.OperationKey}, due to {exception.Message}", exception);
})
.WithPolicyKey("PostgresConnectionPolicy");
我有一个尝试连接到 PostgreSQL 数据库的方法和 运行 使用上述策略的查询:
using (var conn = new NpgsqlConnection("myConnectionString"))
{
conn.Open()
using(var command = GetCommand())
{
policy.Execute(
action: context => command.ExecuteNonQuery(),
contextData: new Context("Command.ExecuteNonQuery"));
}
}
该方法失败,重试,记录器打印以下内容:
Retry 1 of , due to 42P01: relation "myDatabase" does not exist
我希望记录以下内容:
Retry 1 of Command.ExecuteNonQuery, due to 42P01: relation "myDatabase" does not exist
为什么策略记录重试时 OperationKey
为空?
编辑: 添加一个简化的控制台应用程序作为示例。
这会将以下内容打印到控制台:
Retry 1 of , due to Testing Polly
Error.
示例:
using Polly;
using System;
namespace TestPolly
{
class Program
{
static void Main(string[] args)
{
var policy = Policy
.Handle<Exception>()
.Retry(
retryCount: 1,
onRetry: (exception, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} of {context.OperationKey}, due to {exception.Message}");
})
.WithPolicyKey("PostgresConnectionPolicy");
try
{
policy.Execute(
action: context => TestPolly(),
contextData: new Context("TestPolly"));
}
catch (Exception e)
{
Console.WriteLine("Error.");
}
Console.ReadKey();
}
private static void TestPolly()
{
throw new Exception("Testing Polly");
}
}
}
改用自定义上下文解决了这个问题。
政策:
var policy = Policy
.Handle<NpgsqlException>()
.Retry(
retryCount: 1,
onRetry: (exception, retryCount, context) =>
{
_logger.Log(LogLevel.Warning, $"Retry {retryCount} of {context["Operation"]}, due to {exception.Message}", exception);
})
.WithPolicyKey("PostgresConnectionPolicy");
执行:
policy.Execute(
action: context => command.ExecuteNonQuery(),
contextData: new Context() { { "Operation", "Command.ExecuteNonQuery()" } });
上下文对象
- 定义了一些predefined fields(如
OperationKey
、PolicyKey
、CorrelationId
) - 它 implements
IDictionary<string, object>
界面让消费者提供任何 key-value 对。
如果您查看 this line of the source code or the documentation,您会发现有一个构造函数重载接受 OperationKey
.
因此,您可以这样定义执行调用:
policy.Execute(
action: context => command.ExecuteNonQuery(),
contextData: new Context("Command.ExecuteNonQuery()"));
我认为这是一种更好的方法,因为您不依赖 string-based 密钥插入和检索。
更新:我发现了问题。
您一直在使用错误的重载 Execute
。
policy.Execute(
action: context => command.ExecuteNonQuery(),
context: new Context("Command.ExecuteNonQuery()"));
使用 context
而不是 contextData
并且 OperationKey
将会出现。