This is what's being logged:
ex.ToString()
presumably because that's all you're logging. Something like this, I assume, is the logging statement?:
catch (Exception ex)
{
Logger.Log(ex.ToString());
}
The way to add more information to what's being logged is to pass it to the logger. Something like this:
catch (Exception ex)
{
Logger.Log(string.Format("Failed to get a Name for the ID: {0} - Exception was: {1}", ID, ex.ToString()));
}
This is assuming you're logging only strings. You can perhaps expand this to include more strongly-typed data perhaps with custom exceptions being passed directly to the logger itself. It's hard to say without knowing more about the capabilities of the logger. Maybe a custom exception with a generic type parameter which internally adds the parameter to its string representation? Again, it's hard to say in this one simple example without more information.
As for making the whole thing generic, that's really up to your own designs. In the two method signatures you provide there is only one parameter. So a single generic property on a custom exception would work for that. What about methods with multiple parameters? What about methods with context above and beyond its own parameters? (Instance properties on the method's class, for example.)
Each exception is potentially vastly different. Each code block is its own piece of logic in the domain. And providing meaningful context with errors (which is an excellent thing to do, by the way) is often very subjective to those differences in the logic for those code blocks. Sometimes it's strongly typed information, sometimes it's human-readable context about the situation, etc.
Working with legacy code, a workable long-term approach is to identify the errors which require additional information and modify the error-handling code to provide that information. You can often catch a lot of them in one pass to production, but there will be stragglers. In time that number would decrease. It's not the most desirable approach from management's perspective because it often requires two production releases to fix one error (one release to add more logging, another to actually fix the error after the necessary runtime information is provided). But, well, that's the technical debt incurred from such novel gems of bad code as this:
catch (Exception ex)
{
Logger.Log(ex.ToString());
}