CRM 2011 on premise.
I have a plugin written in C#. It could throw exceptions or otherwise behave badly in production.
When this happens I want to capture information about the state and about recent code execution to help me analyse the problem.
Ideally I would like the following:
If the code decides I should know about a problem then I want it to be able to tell me that there was a problem asap, without me looking to see if a problem has occurred.
I want the information about the problem to be easily accessible to me. I don't want to have to RDP to another machine and search through files.
I don't want logging to have much impact on performance.
I guess I'm looking for something like this:
I'm fairly new to CRM but I've developed systems like this before. Since CRM has been around for many years I'd expect this to be available for it.
To support your wish list, I'd create these Entities:
PluginLog
PluginException
Now let's go through your wish list:
To help get you started, this is what I currently use to retrieve all the information from the plugin context, and convert it into text that gets inserted into an Exception:
#region GetPluginInfo
private Exception GetPluginExecutionInfoForLog(IServiceProvider serviceProvider, Exception ex)
{
if(ex.GetType() == typeof(InvalidPluginExecutionException)){ return ex; }
try
{
var context = serviceProvider.GetContext();
ex = new InvalidPluginExecutionException(
String.Format("Error During Plugin Execution: {0}**** Context Values ****{0}{1}",
Environment.NewLine, GetPluginExecutionInfo(context)), ex);
}
catch (Exception childEx)
{
OnError(childEx);
}
return ex;
}
protected String GetPluginExecutionInfo(IPluginExecutionContext context)
{
var lines = new List<String>();
var target = GetTarget<Entity>(context);
lines.Add("MessageName: " + context.MessageName);
lines.Add("PrimaryEntityName: " + context.PrimaryEntityName);
lines.Add("PrimaryEntityId: " + context.PrimaryEntityId);
lines.Add("BusinessUnitId: " + context.BusinessUnitId);
lines.Add("CorrelationId: " + context.CorrelationId);
lines.Add("Depth: " + context.Depth);
lines.Add("Has Parent Context: " + (context.ParentContext != null));
lines.Add("InitiatingUserId: " + context.InitiatingUserId);
AddParameters(lines, context.InputParameters, "Input Parameters");
lines.Add("IsInTransaction: " + context.IsInTransaction);
lines.Add("IsolationMode: " + context.IsolationMode);
lines.Add("Mode: " + context.Mode);
lines.Add("OperationCreatedOn: " + context.OperationCreatedOn);
lines.Add("OperationId: " + context.OperationId);
lines.Add("Organization: " + context.OrganizationName + "(" + context.OrganizationId + ")");
AddParameters(lines, context.OutputParameters, "Output Parameters");
AddEntityReference(lines, context.OwningExtension, "OwningExtension");
AddEntityImages(lines, context.PostEntityImages, "Post Entity Images");
AddEntityImages(lines, context.PreEntityImages, "Pre Entity Images");
lines.Add("SecondaryEntityName: " + context.SecondaryEntityName);
AddParameters(lines, context.SharedVariables, "Shared Variables");
lines.Add("Stage: " + context.Stage);
lines.Add("UserId: " + context.UserId);
if (target == null || target.Attributes.Count == 0)
{
lines.Add("Target: Empty ");
}
else
{
lines.Add("* Target " + target.ToEntityReference().GetNameId() + " *");
foreach (var att in target.Attributes)
{
lines.Add(" Entity[" + att.Key + "]: " + GetAttributeValue(att.Value));
}
}
lines.Add("* App Config Values *");
foreach (var key in ConfigurationManager.AppSettings.AllKeys)
{
lines.Add(" [" + key + "]: " + ConfigurationManager.AppSettings[key]);
}
return String.Join(Environment.NewLine, lines);
}
private static string GetAttributeValue(object value)
{
if(value == null){
return "Null";
}
var type = value.GetType();
if (type == typeof(OptionSetValue))
{
return ((OptionSetValue)value).Value.ToString();
}
else if (type == typeof(EntityReference))
{
return ((EntityReference)value).GetNameId();
}
else
{
return value.ToString();
}
}
private static void AddEntityReference(List<string> nameValuePairs, EntityReference entity, string name)
{
if (entity != null)
{
nameValuePairs.Add(name + ": " + entity.GetNameId());
}
}
private static void AddEntityImages(List<string> nameValuePairs, EntityImageCollection images, string name)
{
if (images != null && images.Count > 0)
{
nameValuePairs.Add("** " + name + " **");
foreach (var image in images)
{
if (image.Value == null || image.Value.Attributes.Count == 0)
{
nameValuePairs.Add(" Image[" + image.Key + "] " + image.Value.ToEntityReference().GetNameId() + ": Empty");
}
else
{
nameValuePairs.Add("* Image[" + image.Key + "] " + image.Value.ToEntityReference().GetNameId() + " *");
foreach (var att in image.Value.Attributes)
{
nameValuePairs.Add(" Entity[" + att.Key + "]: " + GetAttributeValue(att.Value));
}
}
}
}
else
{
nameValuePairs.Add(name + ": Empty");
}
}
private static void AddParameters(List<string> nameValuePairs, ParameterCollection parameters, string name)
{
if (parameters != null && parameters.Count > 0)
{
nameValuePairs.Add("* " + name + " *");
foreach (var param in parameters)
{
nameValuePairs.Add(" Param[" + param.Key + "]: " + param.Value);
}
}
else
{
nameValuePairs.Add(name + ": Empty");
}
}
#endregion // GetPluginInfo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With