Skip to content

Commit

Permalink
Merge pull request #267 from DFE-Digital/logging-request-response
Browse files Browse the repository at this point in the history
Log request/response with payloads
  • Loading branch information
ethax-ross authored Sep 29, 2020
2 parents e9204b9 + 6a8950b commit 69ba358
Show file tree
Hide file tree
Showing 44 changed files with 522 additions and 14 deletions.
2 changes: 1 addition & 1 deletion GetIntoTeachingApi/Attributes/CrmETagAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace GetIntoTeachingApi.Filters
namespace GetIntoTeachingApi.Attributes
{
public class CrmETagAttribute : Attribute, IActionFilter
{
Expand Down
97 changes: 97 additions & 0 deletions GetIntoTeachingApi/Attributes/LogRequestsAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace GetIntoTeachingApi.Attributes
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class LogRequestsAttribute : Attribute, IActionFilter
{
private readonly ILogger<LogRequestsAttribute> _logger;

public LogRequestsAttribute()
{
var factory = LoggerFactory.Create(builder => builder.AddConsole());
_logger = factory.CreateLogger<LogRequestsAttribute>();
}

public LogRequestsAttribute(ILogger<LogRequestsAttribute> logger)
{
_logger = logger;
}

public void OnActionExecuting(ActionExecutingContext context)
{
var descriptor = (ControllerActionDescriptor)context.ActionDescriptor;

var messages = context.ActionArguments.Select(a => LogMessageForObject(a.Value));
var message = LogMessage("Request", descriptor, messages);
_logger.LogInformation(message);
}

public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result is ObjectResult result)
{
var descriptor = (ControllerActionDescriptor)context.ActionDescriptor;
var messages = new List<string> { LogMessageForObject(result.Value) };
var message = LogMessage("Response", descriptor, messages);
_logger.LogInformation(message);
}
}

private static string LogMessage(string type, ControllerActionDescriptor descriptor, IEnumerable<string> messages)
{
var actionName = descriptor.ActionName;
var controllerName = descriptor.ControllerName;
var payload = string.Join("\n", messages.Where(m => !string.IsNullOrEmpty(m)));

return $"{type} {controllerName}:{actionName} - {payload}";
}

private static string LogMessageForObject(object obj)
{
var type = obj.GetType().GetGenericArguments().FirstOrDefault();

if (type == null)
{
type = obj.GetType();
}

if (type.GetCustomAttribute<LoggableAttribute>() == null)
{
return null;
}

return JsonConvert.SerializeObject(
obj,
Formatting.None,
new JsonSerializerSettings
{
ContractResolver = new FilterSensitiveDataContractResolver(),
});
}

private class FilterSensitiveDataContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);

property.ShouldSerialize = instance =>
instance.GetType().GetCustomAttribute<LoggableAttribute>() != null &&
member.GetCustomAttribute<SensitiveDataAttribute>() == null &&
member.GetCustomAttribute<System.Text.Json.Serialization.JsonIgnoreAttribute>() == null;

return property;
}
}
}
}
9 changes: 9 additions & 0 deletions GetIntoTeachingApi/Attributes/LoggableAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace GetIntoTeachingApi.Attributes
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class LoggableAttribute : Attribute
{
}
}
9 changes: 9 additions & 0 deletions GetIntoTeachingApi/Attributes/SensitiveDataAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace GetIntoTeachingApi.Attributes
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class SensitiveDataAttribute : Attribute
{
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -9,6 +10,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/callback_booking_quotas")]
[ApiController]
[LogRequests]
[Authorize]
public class CallbackBookingQuotasController : ControllerBase
{
Expand Down
2 changes: 2 additions & 0 deletions GetIntoTeachingApi/Controllers/CandidatesController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -9,6 +10,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/candidates")]
[ApiController]
[LogRequests]
[Authorize]
public class CandidatesController : ControllerBase
{
Expand Down
2 changes: 2 additions & 0 deletions GetIntoTeachingApi/Controllers/MailingListController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Jobs;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
Expand All @@ -11,6 +12,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/mailing_list")]
[ApiController]
[LogRequests]
[Authorize]
public class MailingListController : ControllerBase
{
Expand Down
3 changes: 2 additions & 1 deletion GetIntoTeachingApi/Controllers/OperationsController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
using GetIntoTeachingApi.Utils;
Expand All @@ -12,6 +12,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/operations")]
[ApiController]
[LogRequests]
public class OperationsController : ControllerBase
{
private readonly IStore _store;
Expand Down
3 changes: 2 additions & 1 deletion GetIntoTeachingApi/Controllers/PrivacyPoliciesController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using GetIntoTeachingApi.Filters;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -11,6 +11,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/privacy_policies")]
[ApiController]
[LogRequests]
[Authorize]
public class PrivacyPoliciesController : ControllerBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Jobs;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
Expand All @@ -11,6 +12,7 @@ namespace GetIntoTeachingApi.Controllers.TeacherTrainingAdviser
{
[Route("api/teacher_training_adviser/candidates")]
[ApiController]
[LogRequests]
[Authorize]
public class CandidatesController : ControllerBase
{
Expand Down
3 changes: 2 additions & 1 deletion GetIntoTeachingApi/Controllers/TeachingEventsController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using GetIntoTeachingApi.Filters;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Jobs;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
Expand All @@ -13,6 +13,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/teaching_events")]
[ApiController]
[LogRequests]
[Authorize]
public class TeachingEventsController : ControllerBase
{
Expand Down
3 changes: 2 additions & 1 deletion GetIntoTeachingApi/Controllers/TypesController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using GetIntoTeachingApi.Filters;
using GetIntoTeachingApi.Attributes;
using GetIntoTeachingApi.Models;
using GetIntoTeachingApi.Services;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -12,6 +12,7 @@ namespace GetIntoTeachingApi.Controllers
{
[Route("api/types")]
[ApiController]
[LogRequests]
[Authorize]
public class TypesController : ControllerBase
{
Expand Down
1 change: 1 addition & 0 deletions GetIntoTeachingApi/Models/CallbackBookingQuota.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace GetIntoTeachingApi.Models
{
[Loggable]
[Entity("dfe_callbackbookingquota")]
public class CallbackBookingQuota : BaseModel
{
Expand Down
2 changes: 2 additions & 0 deletions GetIntoTeachingApi/Models/HealthCheckResponse.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using GetIntoTeachingApi.Attributes;

namespace GetIntoTeachingApi.Models
{
[Loggable]
public class HealthCheckResponse
{
public const string StatusOk = "ok";
Expand Down
7 changes: 7 additions & 0 deletions GetIntoTeachingApi/Models/MailingListAddMember.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Linq;
using System.Text.Json.Serialization;
using GetIntoTeachingApi.Attributes;
using Swashbuckle.AspNetCore.Annotations;

namespace GetIntoTeachingApi.Models
{
[Loggable]
public class MailingListAddMember
{
public Guid? CandidateId { get; set; }
Expand All @@ -18,10 +20,15 @@ public class MailingListAddMember
[SwaggerSchema(WriteOnly = true)]
public int? ChannelId { get; set; }

[SensitiveData]
public string Email { get; set; }
[SensitiveData]
public string FirstName { get; set; }
[SensitiveData]
public string LastName { get; set; }
[SensitiveData]
public string AddressPostcode { get; set; }
[SensitiveData]
public string Telephone { get; set; }
[SwaggerSchema(ReadOnly = true)]
public bool AlreadySubscribedToEvents { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions GetIntoTeachingApi/Models/MappingInfo.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using GetIntoTeachingApi.Attributes;

namespace GetIntoTeachingApi.Models
{
[Loggable]
public class MappingInfo
{
private readonly Type _type;
Expand Down
11 changes: 11 additions & 0 deletions GetIntoTeachingApi/Models/TeacherTrainingAdviserSignUp.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Linq;
using System.Text.Json.Serialization;
using GetIntoTeachingApi.Attributes;
using Swashbuckle.AspNetCore.Annotations;

namespace GetIntoTeachingApi.Models
{
[Loggable]
public class TeacherTrainingAdviserSignUp
{
public Guid? CandidateId { get; set; }
Expand All @@ -25,17 +27,26 @@ public class TeacherTrainingAdviserSignUp
public int? PlanningToRetakeGcseMathsAndEnglishId { get; set; }
public int? PlanningToRetakeGcseScienceId { get; set; }

[SensitiveData]
public string Email { get; set; }
[SensitiveData]
public string FirstName { get; set; }
[SensitiveData]
public string LastName { get; set; }
[SwaggerSchema(Format = "date")]
[SensitiveData]
public DateTime? DateOfBirth { get; set; }
[SensitiveData]
public string TeacherId { get; set; }
public string DegreeSubject { get; set; }
[SensitiveData]
public string Telephone { get; set; }
[SensitiveData]
public string AddressLine1 { get; set; }
[SensitiveData]
public string AddressLine2 { get; set; }
public string AddressCity { get; set; }
[SensitiveData]
public string AddressPostcode { get; set; }
[SwaggerSchema(WriteOnly = true)]
public DateTime? PhoneCallScheduledAt { get; set; }
Expand Down
1 change: 1 addition & 0 deletions GetIntoTeachingApi/Models/TeachingEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace GetIntoTeachingApi.Models
{
[Loggable]
[Entity("msevtmgt_event")]
public class TeachingEvent : BaseModel
{
Expand Down
7 changes: 7 additions & 0 deletions GetIntoTeachingApi/Models/TeachingEventAddAttendee.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Linq;
using System.Text.Json.Serialization;
using GetIntoTeachingApi.Attributes;
using Swashbuckle.AspNetCore.Annotations;

namespace GetIntoTeachingApi.Models
{
[Loggable]
public class TeachingEventAddAttendee
{
public Guid? CandidateId { get; set; }
Expand All @@ -19,10 +21,15 @@ public class TeachingEventAddAttendee
public int? ConsiderationJourneyStageId { get; set; }
public int? DegreeStatusId { get; set; }

[SensitiveData]
public string Email { get; set; }
[SensitiveData]
public string FirstName { get; set; }
[SensitiveData]
public string LastName { get; set; }
[SensitiveData]
public string AddressPostcode { get; set; }
[SensitiveData]
public string Telephone { get; set; }
[SwaggerSchema(ReadOnly = true)]
public bool SubscribeToEvents => AddressPostcode != null && SubscribeToMailingList;
Expand Down
1 change: 1 addition & 0 deletions GetIntoTeachingApi/Models/TeachingEventBuilding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace GetIntoTeachingApi.Models
{
[Loggable]
[Entity("msevtmgt_building")]
public class TeachingEventBuilding : BaseModel
{
Expand Down
Loading

0 comments on commit 69ba358

Please sign in to comment.