Solamente pueden consultarse en los propios registros o de forma general en Configuración->Auditoría->Vista resumen de auditoría:
Si necesitamos consultas algo mas avanzadas, sólo nos queda ir por los oscuros caminos de lo no soportado (atacando directamente al SQL Server), que no lo recomiendo, o sino utilizar la SDK.
En este caso, vamos a ver un ejemplo donde recojo todos los registros de auditorías de los últimos 30 días, y en caso de ser un Update o Create, además muestro el detalle de cambios actualizados.
El ejemplo de código es el siguiente:
static void GetAudit() { //1) Consulta con Filtro de 30 días ConditionExpression cond = new ConditionExpression("createdon", ConditionOperator.LastXDays, 30); FilterExpression filter1 = new FilterExpression(); filter1.AddCondition(cond); RetrieveMultipleRequest req = new RetrieveMultipleRequest(); QueryExpression query = new QueryExpression("audit"); query.ColumnSet = new ColumnSet(true); query.Criteria.AddFilter(filter1); req.Query = query; RetrieveMultipleResponse res =(RetrieveMultipleResponse)service.Execute(req); //2) Recorremos la Auditoria devuelta foreach (Entity ent in res.EntityCollection.Entities) { //3) Leemos los datos del registro Audit record = (Audit)ent; string fecha = String.Format("Fecha:{0}", record.CreatedOn.Value.ToString()); string usuario = String.Format("Usuario:{0}", record.UserId.Name); string accion = String.Format("Action:{0}", record.FormattedValues["action"]); string operacion = String.Format("Operación:{0}", record.FormattedValues["operation"]); string registro = String.Format("Tipo:{0} Name:{1} Guid:{2}", record.ObjectId.LogicalName, record.ObjectId.Name, record.ObjectId.Id.ToString()); //4) Escribimos un log de los datos Console.WriteLine(fecha); Console.WriteLine(usuario); Console.WriteLine(accion); Console.WriteLine(operacion); Console.WriteLine(registro); //5) Si es Create o Update if (record.Action.Value == 1 || record.Action.Value == 2) { //6) Consultamos el detalle RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest(); changeRequest.Target = new EntityReference(record.ObjectId.LogicalName, record.ObjectId.Id); RetrieveRecordChangeHistoryResponse changeResponse = (RetrieveRecordChangeHistoryResponse)service.Execute(changeRequest); AuditDetailCollection details = changeResponse.AuditDetailCollection; foreach (var detail in details.AuditDetails) { //7) Por cada detalle devuelto, pintamos valor anterior y actual Audit detail_record = (Audit)detail.AuditRecord; var detailType = detail.GetType(); if (detailType == typeof(AttributeAuditDetail)) { var attributeDetail = (AttributeAuditDetail)detail; foreach (KeyValuePair<String, object> attribute in attributeDetail.NewValue.Attributes) { String oldValue = "(no value)", newValue = "(no value)"; if (attributeDetail.OldValue.Contains(attribute.Key)) oldValue = attributeDetail.OldValue[attribute.Key].ToString(); newValue = attributeDetail.NewValue[attribute.Key].ToString(); Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}", attribute.Key, oldValue, newValue); } foreach (KeyValuePair<String, object> attribute in attributeDetail.OldValue.Attributes) { if (!attributeDetail.NewValue.Contains(attribute.Key)) { String newValue = "(no value)"; String oldValue = attributeDetail.OldValue[attribute.Key].ToString(); Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}", attribute.Key, oldValue, newValue); } } } } } Console.WriteLine("---------------"); } Console.ReadLine(); }
En resumen, utilizo el mensaje ExecuteMultiple para la consulta general y luego para el detalle utilizo el mensaje RetrieveRecordChangeHistory.
El resultado obtenido en mi caso es el siguiente:
Como puede verse, tengo toda mi auditoría en un resultado ordenado, por fecha, usuario entidad y tipo de acción.
Este ejemplo es 100% funcional, tengo idea de hacer algún tipo de herramienta a futuro, que ayudarnos con los datos que hay en los registros de auditoría, para que sea mas sencillo su explotación.
Espero les sea útil este ejemplo, a mí me ha servido.
Demian, saludos
ResponderEliminarEs viable generar un reporte con Reporting Srevices, que consulte los registros de auditoria de una entidad en especifico?, de ser así, que tablas debería consultar en SQL ademas de AuditBase o la vista Audit.}
Gracias