Skip to content

Commit 126a85c

Browse files
committed
#30588 Audit sample fixed.
1 parent 70ad7a5 commit 126a85c

17 files changed

+394
-162
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using PostSharp.Patterns.Diagnostics;
2+
using PostSharp.Samples.Logging.Audit.Audit.Backend;
3+
4+
namespace PostSharp.Samples.Logging.Audit.Audit
5+
{
6+
/// <summary>
7+
/// Custom attribute that, when applied to a method, causes PostSharp to audit execution of this method. Whenever an audited method is executed, the
8+
/// <see cref="AuditServices.RecordPublished"/> event is raised. You need to register your own logic to the <see cref="AuditServices.RecordPublished"/> event,
9+
/// for instance to append the record to a database table.
10+
/// </summary>
11+
/// <remarks>
12+
/// <para>Audit is a special kind of logging. The <see cref="AuditAttribute"/> aspects adds logging with the <c>Audit</c> profile, which is by default served
13+
/// by the <see cref="AuditBackend"/> back-end, which exposes a simple API to the <see cref="AuditServices"/> class.
14+
/// </para>
15+
/// <para>The <see cref="AuditAttribute"/> aspect can be used side-by-side with the <see cref="LogAttribute"/> aspect.</para>
16+
/// </remarks>
17+
public sealed class AuditAttribute : LogAttributeBase
18+
{
19+
/// <summary>
20+
/// Initializes a new <see cref="AuditAttribute"/>.
21+
/// </summary>
22+
public AuditAttribute()
23+
{
24+
this.ProfileName = "Audit";
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using PostSharp.Patterns.Diagnostics;
3+
4+
namespace PostSharp.Samples.Logging.Audit.Audit
5+
{
6+
/// <summary>
7+
/// Represents an audit record published by the <see cref="AuditServices.RecordPublished"/> event.
8+
/// </summary>
9+
/// <remarks>
10+
/// <para>
11+
/// You can customize this class by inheritance. In this case, you also need to customize the <see cref="AuditBackend"/> and
12+
/// <see cref="AuditRecordBuilder"/> classes.
13+
/// </para>
14+
/// </remarks>
15+
public class AuditRecord
16+
{
17+
/// <summary>
18+
/// Initializes a new <see cref="AuditRecord"/>.
19+
/// </summary>
20+
/// <param name="declaringType">Declaring type of the audited method.</param>
21+
/// <param name="memberName">Name of the audited method.</param>
22+
/// <param name="recordKind">Kind of record (typically <see cref="LogRecordKind.MethodSuccess"/> or <see cref="LogRecordKind.MethodException"/>).</param>
23+
public AuditRecord(Type declaringType, string memberName, LogRecordKind recordKind)
24+
{
25+
this.MemberName = memberName;
26+
this.RecordKind = recordKind;
27+
this.DeclaringType = declaringType;
28+
this.Time = DateTime.Now;
29+
}
30+
31+
/// <summary>
32+
/// Gets the time when the execution ended.
33+
/// </summary>
34+
public DateTime Time
35+
{
36+
get;
37+
}
38+
39+
/// <summary>
40+
/// Gets the declaring type of the method.
41+
/// </summary>
42+
public Type DeclaringType
43+
{
44+
get;
45+
}
46+
47+
/// <summary>
48+
/// Gets the name of the method.
49+
/// </summary>
50+
public string MemberName
51+
{
52+
get;
53+
}
54+
55+
/// <summary>
56+
/// Gets the kind of record (typically <see cref="LogRecordKind.MethodSuccess"/> or <see cref="LogRecordKind.MethodException"/>).
57+
/// </summary>
58+
public LogRecordKind RecordKind
59+
{
60+
get;
61+
}
62+
63+
/// <summary>
64+
/// Gets a string describing the operation (typically, the method type, name, and parameters).
65+
/// </summary>
66+
public string Text
67+
{
68+
get; set;
69+
}
70+
71+
/// <summary>
72+
/// Gets the <see cref="Exception"/> if the method failed, or <c>null</c> if the method succeeded.
73+
/// </summary>
74+
public Exception Exception
75+
{
76+
get; set;
77+
}
78+
79+
/// <summary>
80+
/// Gets the instance on which the method was executed, or <c>null</c> if the method is a static method.
81+
/// </summary>
82+
public object Target
83+
{
84+
get; set;
85+
}
86+
}
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
3+
namespace PostSharp.Samples.Logging.Audit.Audit
4+
{
5+
/// <summary>
6+
/// Arguments of the <see cref="AuditServices.RecordPublished"/> event.
7+
/// </summary>
8+
public class AuditRecordEventArgs : EventArgs
9+
{
10+
/// <summary>
11+
/// Gets the published record.
12+
/// </summary>
13+
public AuditRecord Record
14+
{
15+
get;
16+
}
17+
18+
/// <summary>
19+
/// Initializes a new <see cref="AuditRecordEventArgs"/>.
20+
/// </summary>
21+
/// <param name="record">The published <see cref="AuditRecord"/>.</param>
22+
public AuditRecordEventArgs(AuditRecord record)
23+
{
24+
this.Record = record;
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
namespace PostSharp.Samples.Logging.Audit.Audit
4+
{
5+
/// <summary>
6+
/// Exposes a <see cref="RecordPublished"/> event, which is raised whenever an audited method is executed.
7+
/// </summary>
8+
public static class AuditServices
9+
{
10+
internal static void PublishRecord(AuditRecord currentRecord)
11+
{
12+
RecordPublished?.Invoke(null, new AuditRecordEventArgs(currentRecord));
13+
}
14+
15+
/// <summary>
16+
/// Event raised whenever an audited method is executed.
17+
/// </summary>
18+
public static event EventHandler<AuditRecordEventArgs> RecordPublished;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using PostSharp.Patterns.Diagnostics;
2+
using PostSharp.Patterns.Diagnostics.Backends;
3+
using PostSharp.Patterns.Diagnostics.RecordBuilders;
4+
using System;
5+
6+
namespace PostSharp.Samples.Logging.Audit.Audit.Backend
7+
{
8+
/// <summary>
9+
/// A specialized back-end that publishes audit records to the <see cref="AuditServices.RecordPublished"/> event.
10+
/// </summary>
11+
public class AuditBackend : TextLoggingBackend
12+
{
13+
/// <summary>
14+
/// Initializes a new <see cref="AuditBackend"/>.
15+
/// </summary>
16+
public AuditBackend()
17+
{
18+
}
19+
20+
21+
/// <summary>
22+
/// Publishes an <see cref="AuditRecord"/> to the <see cref="AuditServices.RecordPublished"/> event.
23+
/// </summary>
24+
/// <param name="record"></param>
25+
public virtual void PublishRecord(AuditRecord record)
26+
{
27+
AuditServices.PublishRecord(record);
28+
}
29+
30+
31+
/// <inheritdoc />
32+
protected override LoggingTypeSource CreateTypeSource(LoggingNamespaceSource parent, Type type)
33+
{
34+
return new AuditTypeSource(parent, type);
35+
}
36+
37+
/// <inheritdoc />
38+
public override LogRecordBuilder CreateRecordBuilder()
39+
{
40+
return new AuditRecordBuilder(this);
41+
}
42+
43+
/// <summary>
44+
/// Gets the back-end options.
45+
/// </summary>
46+
public new AuditBackendOptions Options { get; } = new AuditBackendOptions();
47+
48+
/// <inheritdoc />
49+
protected override TextLoggingBackendOptions GetTextBackendOptions() => this.Options;
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using PostSharp.Patterns.Diagnostics.Backends;
2+
3+
namespace PostSharp.Samples.Logging.Audit.Audit.Backend
4+
{
5+
/// <summary>
6+
/// Options of <see cref="AuditBackend"/>.
7+
/// </summary>
8+
public class AuditBackendOptions : TextLoggingBackendOptions
9+
{
10+
/// <summary>
11+
/// Initializes a new <see cref="AuditBackendOptions"/>.
12+
/// </summary>
13+
public AuditBackendOptions()
14+
{
15+
this.IndentSpaces = 0;
16+
}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using PostSharp.Patterns.Diagnostics.Contexts;
2+
using PostSharp.Patterns.Diagnostics.RecordBuilders;
3+
using PostSharp.Patterns.Formatters;
4+
using System;
5+
6+
namespace PostSharp.Samples.Logging.Audit.Audit.Backend
7+
{
8+
/// <summary>
9+
/// Record builder for the <see cref="AuditBackend"/>.
10+
/// </summary>
11+
public class AuditRecordBuilder : TextLogRecordBuilder
12+
{
13+
14+
/// <summary>
15+
/// Creates an <see cref="AuditRecord"/>.
16+
/// </summary>
17+
/// <param name="context">The context of the record.</param>
18+
/// <param name="recordInfo">Information about the record.</param>
19+
/// <param name="memberInfo">Information about the method, property, or field.</param>
20+
/// <returns>An <see cref="AuditRecord"/>.</returns>
21+
protected virtual AuditRecord CreateRecord(LoggingContext context, ref LogRecordInfo recordInfo, ref LogMemberInfo memberInfo)
22+
{
23+
#pragma warning disable CS0618 // Type or member is obsolete
24+
return new AuditRecord(memberInfo.Source.SourceType, memberInfo.MemberName, recordInfo.RecordKind);
25+
#pragma warning restore CS0618 // Type or member is obsolete
26+
}
27+
28+
/// <inheritdoc />
29+
public override void BeginRecord(LoggingContext context, ref LogRecordInfo recordInfo, ref LogMemberInfo memberInfo)
30+
{
31+
base.BeginRecord(context, ref recordInfo, ref memberInfo);
32+
33+
this.CurrentRecord = this.CreateRecord(context, ref recordInfo, ref memberInfo);
34+
35+
}
36+
37+
/// <summary>
38+
/// Gets the current <see cref="AuditBackend"/>.
39+
/// </summary>
40+
public new AuditBackend Backend
41+
{
42+
get;
43+
}
44+
45+
/// <summary>
46+
/// Initializes a new <see cref="AuditRecordBuilder"/>.
47+
/// </summary>
48+
/// <param name="backend">The parent <see cref="AuditBackend"/>.</param>
49+
public AuditRecordBuilder(AuditBackend backend) : base(backend)
50+
{
51+
this.Backend = backend;
52+
}
53+
54+
/// <summary>
55+
/// Gets the <see cref="AuditRecord"/> being currently built.
56+
/// </summary>
57+
public AuditRecord CurrentRecord
58+
{
59+
get; private set;
60+
}
61+
62+
/// <inheritdoc />
63+
public override void SetException(Exception exception)
64+
{
65+
base.SetException(exception);
66+
67+
this.CurrentRecord.Exception = exception;
68+
}
69+
70+
/// <inheritdoc />
71+
public override void SetThis<T>(T value, IFormatter<T> formatter)
72+
{
73+
// We don't want to include the value in the text.
74+
// base.SetThis<T>(value, formatter);
75+
76+
this.CurrentRecord.Target = value;
77+
}
78+
79+
/// <inheritdoc />
80+
protected override void Write(UnsafeString message)
81+
{
82+
if (this.CurrentRecord != null)
83+
{
84+
this.CurrentRecord.Text = this.Context.Description.ToString();
85+
this.Backend.PublishRecord(this.CurrentRecord);
86+
this.CurrentRecord = null;
87+
}
88+
}
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using PostSharp.Patterns.Diagnostics;
2+
using System;
3+
4+
namespace PostSharp.Samples.Logging.Audit.Audit.Backend
5+
{
6+
/// <summary>
7+
/// Represents a type logged using the <see cref="AuditBackend"/>.
8+
/// </summary>
9+
public class AuditTypeSource : LoggingTypeSource
10+
{
11+
/// <summary>
12+
/// Initializes a new <see cref="AuditTypeSource"/>.
13+
/// </summary>
14+
/// <param name="parent">The parent <see cref="LoggingNamespaceSource"/>.</param>
15+
/// <param name="type">The declaring type of audited methods.</param>
16+
public AuditTypeSource(LoggingNamespaceSource parent, Type type) : base(parent, type.FullName, type)
17+
{
18+
}
19+
20+
/// <inheritdoc />
21+
protected override bool IsBackendEnabled(LogLevel level)
22+
{
23+
return true;
24+
}
25+
}
26+
}

Diagnostics/PostSharp.Samples.Logging.Audit/AuditAttribute.cs

-27
This file was deleted.

0 commit comments

Comments
 (0)