Audit.WebApi
27.0.3
dotnet add package Audit.WebApi --version 27.0.3
NuGet\Install-Package Audit.WebApi -Version 27.0.3
<PackageReference Include="Audit.WebApi" Version="27.0.3" />
paket add Audit.WebApi --version 27.0.3
#r "nuget: Audit.WebApi, 27.0.3"
// Install Audit.WebApi as a Cake Addin #addin nuget:?package=Audit.WebApi&version=27.0.3 // Install Audit.WebApi as a Cake Tool #tool nuget:?package=Audit.WebApi&version=27.0.3
Audit.WebApi
ASP.NET MVC Web API Audit Extension for Audit.NET library (An extensible framework to audit executing operations in .NET).
Generate Audit Trails for ASP.NET MVC Web API calls. This library provides a configurable infrastructure to log interactions with your Asp.NET (or Asp.NET Core) Web API.
Install
NuGet Package
To install the ASP.NET package run the following command on the Package Manager Console:
PM> Install-Package Audit.WebApi
To install the Asp Net Core package:
PM> Install-Package Audit.WebApi.Core
IMPORTANT NOTE
Previously, it was possible to reference the Audit.WebApi
package for ASP.NET Core MVC.
However, starting from version 23, the Audit.WebApi
package is now exclusively designed for ASP.NET Framework MVC,
whereas the Audit.WebApi.Core
package is exclusively tailored for ASP.NET Core MVC.
Please upgrade your references accordingly.
How it works
This library is implemented as an action filter that intercepts the execution of action methods to generate a detailed audit trail.
For Asp.NET Core, it is also implemented as a Middleware class that can be configured to log requests that does not reach the action filter (i.e. unsolved routes, parsing errors, etc).
Usage
The audit can be enabled in different ways:
- Local Action Filter: Decorating the controllers/actions to be audited with
AuditApi
action filter attribute. - Global Action Filter: Adding the
AuditApiGlobalFilter
action filter as a global filter. This method allows more dynamic configuration of the audit settings. - Middleware (Asp.Net Core): Adding the
AuditMiddleware
to the pipeline. This method allow to audit request that doesn't get to the action filter. - Middleware + Action Filters (Asp.Net Core): Adding the Audit Middleware together with the Global Action Filter (or Local Action Filters). This is the recommended approach.
1- Local Action Filter
Decorate your controller with AuditApiAttribute
:
using Audit.WebApi;
public class UsersController : ApiController
{
[AuditApi]
public IEnumerable<ApplicationUser> Get()
{
//...
}
[AuditApi(EventTypeName = "GetUser",
IncludeHeaders = true, IncludeResponseHeaders = true, IncludeResponseBody = true, IncludeRequestBody = true, IncludeModelState = true)]
public IHttpActionResult Get(string id)
{
//...
}
}
You can also decorate the controller class with the AuditApi
attribute so it will apply to all the actions, for example:
using Audit.WebApi;
[AuditApi(EventTypeName = "{controller}/{action} ({verb})", IncludeResponseBody = true, IncludeRequestBody = true, IncludeModelState = true)]
public class UsersController : ApiController
{
public IEnumerable<ApplicationUser> Get()
{
//...
}
public IHttpActionResult Get(string id)
{
//...
}
}
You can also add the AuditApiAttribute
as a global filter, for example for Asp.NET Core:
using Audit.WebApi;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(_ => _
.Filters.Add(new AuditApiAttribute()));
}
}
Note
For custom configuration it is recommended to use the
AuditApiGlobalFilter
as a global filter. See next section.
2- Global Action Filter
Alternatively, you can add one or more AuditApiGlobalFilter
as global action filters.
This method allows to dynamically change the audit settings as functions of the context, via a fluent API.
Note this action filter cannot be used to statically decorate the controllers.
using Audit.WebApi;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(mvc =>
{
mvc.AddAuditFilter(config => config
.LogActionIf(d => d.ControllerName == "Orders" && d.ActionName != "GetOrder")
.WithEventType("{verb}.{controller}.{action}")
.IncludeHeaders(ctx => !ctx.ModelState.IsValid)
.IncludeRequestBody()
.IncludeModelState()
.IncludeResponseBody(ctx => ctx.HttpContext.Response.StatusCode == 200));
});
}
3- Middleware
For Asp.NET Core, you can additionally (or alternatively) configure a middleware to be able to log requests that doesn't get into an action filter (i.e. request that cannot be routed, etc).
On your startup Configure
method, call the UseAuditMiddleware()
extension method:
using Audit.WebApi;
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseAuditMiddleware(_ => _
.FilterByRequest(rq => !rq.Path.Value.EndsWith("favicon.ico"))
.WithEventType("{verb}:{url}")
.IncludeHeaders()
.IncludeResponseHeaders()
.IncludeRequestBody()
.IncludeResponseBody());
app.UseMvc();
}
}
Warning
You should call
UseAuditMiddleware()
beforeUseMvc()
, otherwise the middleware will not be able to process MVC actions.
If you only configure the middleware (no audit action filters) but want to ignore actions via [AuditIgnoreAttribute]
, you must
add an action filter to discard the AuditScope
. This is needed because the middleware cannot inspect the
MVC action attributes. You can use the AuditIgnoreActionFilter
for this purpose, adding it to the MVC pipeline like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(mvc =>
{
mvc.Filters.Add(new AuditIgnoreActionFilter());
});
}
4- Middleware + Action Filters
You can mix the Audit Middleware together with the Global Action Filter (and/or Local Action Filters). Take into account that:
- Middleware will log any request regardless if an MVC action is reached or not.
- If an action is reached, the Action Filter will include specific MVC context info to the Audit Event.
- Only one Audit Event is generated per request, regardless of an action being processed by the Middleware and multiple Action Filters.
- The
AuditIgnore
attribute is handled by the Action Filters, there is no need to add theAuditIgnoreActionFilter
to the MVC filters when using a mixed approach.
Configuration
Output
The audit events are stored using a Data Provider. You can use one of the available data providers or implement your own. Please refer to the data providers section on Audit.NET documentation.
You can setup the data provider to use by registering an instance of an AuditDataProdiver
to the IServiceCollection
on your start-up code, for example:
var dataProvider = new FileDataProvider(cfg => cfg.Directory(@"C:\Logs"));
services.AddSingleton<AuditDataProvider>(dataProvider);
Or, alternatively, you can setup the data provider globally with the static configuration:
Audit.Core.Configuration.DataProvider = new FileDataProvider(cfg => cfg.Directory(@"C:\Logs"));
Or using the fluent API:
Audit.Core.Configuration.Setup()
.UseFileLogProvider(cfg => cfg.Directory(@"C:\Logs"));
Settings (Action Filter)
The AuditApiAttribute
can be configured with the following properties:
- EventTypeName: A string that identifies the event type. Can contain the following placeholders:
- {controller}: replaced with the controller name.
- {action}: replaced with the action method name.
- {verb}: replaced with the HTTP verb used (GET, POST, etc).
- IncludeHeaders: Boolean to indicate whether to include the Http Request Headers or not. Default is false.
- IncludeResponseHeaders: Boolean to indicate whether to include the Http Response Headers or not. Default is false.
- IncludeRequestBody: Boolean to indicate whether to include or exclude the request body from the logs. Default is false. (Check the following note)
- IncludeResponseBody: Boolean to indicate whether to include response body or not. Default is false.
- IncludeResponseBodyFor: Alternative to IncludeResponseBody, to allow conditionally including the response body on the log, when certain Http Status Codes are returned.
- ExcludeResponseBodyFor: Alternative to IncludeResponseBody, to allow conditionally excluding the response body from the log, when certain Http Status Codes are returned.
- IncludeModelState: Boolean to indicate whether to include the Model State info or not. Default is false.
- SerializeActionParameters: Boolean to indicate whether the action arguments should be pre-serialized to the audit event. Default is false.
The AuditApiGlobalFilter
can be configured with the following methods:
- LogActionIf() / LogRequestIf(): A function of the
ContollerActionDescriptor
/HttpRequest
to determine whether the action should be logged or not. - WithEventType(): A string (or a function of the executing context that returns a string) that identifies the event type. Can contain the following placeholders:
- {controller}: replaced with the controller name.
- {action}: replaced with the action method name.
- {verb}: replaced with the HTTP verb used (GET, POST, etc).
- {url}: replaced with the request URL.
- IncludeHeaders(): Boolean (or function of the executing context that returns a boolean) to indicate whether to include the Http Request Headers or not. Default is false.
- IncludeResponseHeaders(): Boolean (or function of the executing context that returns a boolean) to indicate whether to include the Http Response Headers or not. Default is false.
- IncludeRequestBody(): Boolean (or function of the executing context that returns a boolean) to indicate whether to include or exclude the request body from the logs. Default is false. (Check the following note)
- IncludeResponseBody(): Boolean (or function of the executed context that returns a boolean) to indicate whether to include response body or not. Default is false.
- IncludeModelState(): Boolean (or function of the executed context that returns a boolean) to indicate whether to include the Model State info or not. Default is false.
- SerializeActionParameters(): Boolean to indicate whether the action arguments should be pre-serialized to the audit event. Default is false.
To configure the output persistence mechanism please see Event Output Configuration.
NOTE
When IncludeRequestBody is set to true (or when using IncludeRequestBodyFor/ExcludeRequestBodyFor), you must enable rewind on the request body stream, otherwise, the controller won't be able to read the request body since by default, it's a forward-only stream that can be read only once. You can enable rewind on your startup logic with the following code:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (context, next) => { // <----
context.Request.EnableBuffering(); // or .EnableRewind();
await next();
});
app.UseMvc();
}
Settings (Middleware)
- FilterByRequest(): A function of the
HttpRequest
to determine whether the request should be logged or not, by default all requests are logged. - IncludeHeaders(): Boolean (or function of the HTTP context that returns a boolean) to indicate whether to include the Http Request Headers or not. Default is false.
- IncludeResponseHeaders(): Boolean (or function of the HTTP context that returns a boolean) to indicate whether to include the Http Response Headers or not. Default is false.
- IncludeRequestBody(): Boolean (or function of the HTTP context that returns a boolean) to indicate whether to include or exclude the request body from the logs. Default is false. (Check the following note)
- IncludeResponseBody(): Boolean (or a predicate of the HTTP context before execution) to indicate whether to include response body. The predicate is evaluated before action execution. Default is false.
- SkipResponseBodyContent(): Boolean (or a predicate of the HTTP context after execution) to indicate whether to skip or include the response body content. The predicate is evaluated after action execution. Default is false.
- WithEventType(): A string (or a function of the HTTP context that returns a string) that identifies the event type. Can contain the following placeholders (default is "{verb} {url}"):
- {verb}: replaced with the HTTP verb used (GET, POST, etc).
- {url}: replaced with the request URL.
Audit Ignore attribute
To selectively exclude certain controllers, actions, action parameters or action responses, you can decorate them with AuditIgnore
attribute.
For example:
[Route("api/[controller]")]
[AuditApi(EventTypeName = "{controller}/{action}")]
public class AccountController : Controller
{
[HttpGet]
[AuditIgnore]
public IEnumerable<string> GetAccounts()
{
// this action will not be audited
}
[HttpPost]
public IEnumerable<string> PostAccount(string user, [AuditIgnore]string password)
{
// password argument will not be audited
}
[HttpGet]
[return:AuditIgnore]
public IEnumerable<string> GetSecrets()
{
// the return value of this action will not be audited
}
}
Output details
The following table describes the Audit.WebApi output fields:
Action
Field Name | Type | Description |
---|---|---|
TraceId | string | A unique identifier per request |
HttpMethod | string | HTTP method (GET, POST, etc) |
ControllerName | string | The controller name |
ActionName | string | The action name |
FormVariables | Object | Form-data input variables passed to the action |
ActionParameters | Object | The action parameters passed |
UserName | string | Username on the HttpContext Identity |
RequestUrl | string | URL of the request |
IpAddress | string | Client IP address |
ResponseStatusCode | integer | HTTP response status code |
ResponseStatus | string | Response status description |
RequestBody | BodyContent | The request body (optional) |
ResponseBody | BodyContent | The response body (optional) |
Headers | Object | HTTP Request Headers (optional) |
ResponseHeaders | Object | HTTP Response Headers (optional) |
ModelStateValid | boolean | Boolean to indicate if the model is valid |
ModelStateErrors | string | Error description when the model is invalid |
Exception | string | The exception thrown details (if any) |
BodyContent
Field Name | Type | Description |
---|---|---|
Type | string | The body type reported |
Length | long? | The length of the body if reported |
Value | Object | The body content |
Customization
You can access the Audit Scope object for customization from the API controller action by calling the ApiController extension method GetCurrentAuditScope()
.
For example:
[AuditApi]
public class UsersController : ApiController
{
public IHttpActionResult Get(string id)
{
//...
var auditScope = this.GetCurrentAuditScope();
auditScope.Comment("New comment from controller");
auditScope.SetCustomField("TestField", Guid.NewGuid());
//...
}
}
See Audit.NET documentation about Custom Field and Comments for more information.
Output Sample
{
"EventType":"POST Values/Post",
"Environment":{
"UserName":"Federico",
"MachineName":"HP",
"DomainName":"HP",
"CallingMethodName":"WebApiTest.Controllers.ValuesController.Post()",
"AssemblyName":"WebApiTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Culture":"en-US"
},
"StartDate":"2017-03-09T18:03:05.5287603-06:00",
"EndDate":"2017-03-09T18:03:05.5307604-06:00",
"Duration":2,
"Action":{
"TraceId": "0HLFLQP4HGFAF_00000001",
"HttpMethod":"POST",
"ControllerName":"Values",
"ActionName":"Post",
"ActionParameters":{
"value":{
"Id":100,
"Text":"Test"
}
},
"FormVariables":{
},
"RequestUrl":"http://localhost:65080/api/values",
"IpAddress":"127.0.0.1",
"ResponseStatus":"OK",
"ResponseStatusCode":200,
"RequestBody":{
"Type":"application/json",
"Length":27,
"Value":"{ Id: 100, Text: \"Test\" }"
},
"ResponseBody":{
"Type":"SomeObject",
"Value":{
"Id":1795824380,
"Text":"Test"
}
},
"Headers": {
"Connection": "Keep-Alive",
"Accept": "text/html, application/xhtml+xml, image/jxr, */*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-GB",
"Host": "localhost:37341",
"User-Agent": "Mozilla/5.0, (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0), like, Gecko"
}
}
}
Web API template (dotnet new)
If you are creating an ASP.NET Core Web API project from scratch, you can use the dotnet new template provided on the library Audit.WebApi.Template. This allows to quickly generate an audit-enabled Web API project that can be used as a starting point for your project or as a working example.
To install the template on your system, just type:
dotnet new -i Audit.WebApi.Template
Once you install the template, you should see it on the dotnet new templates list with the name webapiaudit
as follows:
You can now create a new project on the current folder by running:
dotnet new webapiaudit
This will create a new Asp.NET Core project.
You can optionally include Entity Framework Core by adding the -E
parameter
dotnet new webapiaudit -E
Also you can include a service interceptor (using Audit.DynamicProxy) for your service dependencies calls, by adding the -S
parameter
dotnet new webapiaudit -S
To get help about the options:
dotnet new webapiaudit -h
Contribute
If you like this project please contribute in any of the following ways:
- Star this project on GitHub.
- Request a new feature or expose any bug you found by creating a new issue.
- Ask any questions about the library on StackOverflow.
- Subscribe to and use the Gitter Audit.NET channel.
- Support the project by becoming a Backer:
- Spread the word by blogging about it, or sharing it on social networks: <p class="share-buttons"> <a href="https://www.facebook.com/sharer/sharer.php?u=https://nuget.org/packages/Audit.NET/&t=Check+out+Audit.NET" target="_blank"> <img width="24" height="24" alt="Share this package on Facebook" src="https://nuget.org/Content/gallery/img/facebook.svg" / > </a> <a href="https://twitter.com/intent/tweet?url=https://nuget.org/packages/Audit.NET/&text=Check+out+Audit.NET" target="_blank"> <img width="24" height="24" alt="Tweet this package" src="https://nuget.org/Content/gallery/img/twitter.svg" /> </a> </p>
- Make a donation via PayPal
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
-
.NETFramework 4.6.2
- Audit.NET (>= 27.0.3)
- Microsoft.AspNet.WebApi.Core (>= 5.3.0)
- Microsoft.AspNet.WebApi.Owin (>= 5.3.0)
- System.Text.Json (>= 6.0.9)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Audit.WebApi:
Package | Downloads |
---|---|
RezisFramework
Package Description |
|
BuildingBlocks.Logging
Componente para geração de logs. |
|
TimCodes.Auditing.Web
Assists in auditing actions |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Audit.WebApi:
Repository | Stars |
---|---|
thepirat000/spleeter-api
Audio separation API using Spleeter from Deezer
|
Version | Downloads | Last updated |
---|---|---|
27.0.3 | 101 | 9/25/2024 |
27.0.2 | 98 | 9/19/2024 |
27.0.1 | 129 | 9/4/2024 |
27.0.0 | 92 | 9/3/2024 |
26.0.1 | 185 | 8/22/2024 |
26.0.0 | 321 | 7/19/2024 |
25.0.7 | 938 | 7/4/2024 |
25.0.6 | 443 | 6/24/2024 |
25.0.5 | 574 | 6/18/2024 |
25.0.4 | 1,961 | 3/24/2024 |
25.0.3 | 158 | 3/13/2024 |
25.0.2 | 254 | 3/12/2024 |
25.0.1 | 169 | 2/28/2024 |
25.0.0 | 262 | 2/16/2024 |
24.0.1 | 157 | 2/12/2024 |
24.0.0 | 119 | 2/12/2024 |
23.0.0 | 605 | 12/14/2023 |
22.1.0 | 6,146 | 12/9/2023 |
22.0.2 | 974 | 12/1/2023 |
22.0.1 | 5,131 | 11/16/2023 |
22.0.0 | 352 | 11/14/2023 |
21.1.0 | 12,822 | 10/9/2023 |
21.0.4 | 6,832 | 9/15/2023 |
21.0.3 | 12,053 | 7/9/2023 |
21.0.2 | 255 | 7/6/2023 |
21.0.1 | 17,923 | 5/27/2023 |
21.0.0 | 9,725 | 4/15/2023 |
20.2.4 | 2,725 | 3/27/2023 |
20.2.3 | 7,738 | 3/17/2023 |
20.2.2 | 340 | 3/14/2023 |
20.2.1 | 4,661 | 3/11/2023 |
20.2.0 | 796 | 3/7/2023 |
20.1.6 | 848 | 2/23/2023 |
20.1.5 | 3,564 | 2/9/2023 |
20.1.4 | 15,342 | 1/28/2023 |
20.1.3 | 5,531 | 12/21/2022 |
20.1.2 | 1,293 | 12/14/2022 |
20.1.1 | 368 | 12/12/2022 |
20.1.0 | 603 | 12/4/2022 |
20.0.4 | 2,281 | 11/30/2022 |
20.0.3 | 7,980 | 10/28/2022 |
20.0.2 | 490 | 10/26/2022 |
20.0.1 | 530 | 10/21/2022 |
20.0.0 | 7,236 | 10/1/2022 |
19.4.1 | 10,569 | 9/10/2022 |
19.4.0 | 950 | 9/2/2022 |
19.3.0 | 1,090 | 8/23/2022 |
19.2.2 | 2,919 | 8/11/2022 |
19.2.1 | 2,082 | 8/6/2022 |
19.2.0 | 2,190 | 7/24/2022 |
19.1.4 | 35,552 | 5/23/2022 |
19.1.3 | 634 | 5/22/2022 |
19.1.2 | 653 | 5/18/2022 |
19.1.1 | 1,441 | 4/28/2022 |
19.1.0 | 6,683 | 4/10/2022 |
19.0.7 | 39,708 | 3/13/2022 |
19.0.6 | 876 | 3/7/2022 |
19.0.5 | 8,007 | 1/28/2022 |
19.0.4 | 2,445 | 1/23/2022 |
19.0.3 | 7,944 | 12/14/2021 |
19.0.2 | 513 | 12/11/2021 |
19.0.1 | 8,115 | 11/20/2021 |
19.0.0 | 5,088 | 11/11/2021 |
19.0.0-rc.net60.2 | 169 | 9/26/2021 |
19.0.0-rc.net60.1 | 215 | 9/16/2021 |
18.1.6 | 41,256 | 9/26/2021 |
18.1.5 | 1,735 | 9/7/2021 |
18.1.4 | 580 | 9/6/2021 |
18.1.3 | 6,395 | 8/19/2021 |
18.1.2 | 695 | 8/8/2021 |
18.1.1 | 619 | 8/5/2021 |
18.1.0 | 1,279 | 8/1/2021 |
18.0.1 | 2,972 | 7/30/2021 |
18.0.0 | 4,298 | 7/26/2021 |
17.0.8 | 11,402 | 7/7/2021 |
17.0.7 | 1,012 | 6/16/2021 |
17.0.6 | 2,136 | 6/5/2021 |
17.0.5 | 1,453 | 5/28/2021 |
17.0.4 | 7,215 | 5/4/2021 |
17.0.3 | 673 | 5/1/2021 |
17.0.2 | 20,678 | 4/22/2021 |
17.0.1 | 659 | 4/18/2021 |
17.0.0 | 4,382 | 3/26/2021 |
16.5.6 | 2,403 | 3/25/2021 |
16.5.5 | 1,592 | 3/23/2021 |
16.5.4 | 871 | 3/9/2021 |
16.5.3 | 675 | 2/26/2021 |
16.5.2 | 879 | 2/23/2021 |
16.5.1 | 681 | 2/21/2021 |
16.5.0 | 966 | 2/17/2021 |
16.4.5 | 648 | 2/15/2021 |
16.4.4 | 2,087 | 2/5/2021 |
16.4.3 | 6,101 | 1/27/2021 |
16.4.2 | 819 | 1/22/2021 |
16.4.1 | 710 | 1/21/2021 |
16.4.0 | 2,370 | 1/11/2021 |
16.3.3 | 687 | 1/8/2021 |
16.3.2 | 823 | 1/3/2021 |
16.3.1 | 3,012 | 12/31/2020 |
16.3.0 | 669 | 12/30/2020 |
16.2.1 | 1,381 | 12/27/2020 |
16.2.0 | 10,464 | 10/13/2020 |
16.1.5 | 4,190 | 10/4/2020 |
16.1.4 | 1,820 | 9/17/2020 |
16.1.3 | 1,132 | 9/13/2020 |
16.1.2 | 724 | 9/9/2020 |
16.1.1 | 781 | 9/3/2020 |
16.1.0 | 2,185 | 8/19/2020 |
16.0.3 | 851 | 8/15/2020 |
16.0.2 | 14,466 | 8/9/2020 |
16.0.1 | 880 | 8/8/2020 |
16.0.0 | 794 | 8/7/2020 |
15.3.0 | 24,641 | 7/23/2020 |
15.2.3 | 1,593 | 7/14/2020 |
15.2.2 | 5,859 | 5/19/2020 |
15.2.1 | 7,272 | 5/12/2020 |
15.2.0 | 864 | 5/9/2020 |
15.1.1 | 980 | 5/4/2020 |
15.1.0 | 6,497 | 4/13/2020 |
15.0.5 | 5,890 | 3/18/2020 |
15.0.4 | 4,906 | 2/28/2020 |
15.0.3 | 855 | 2/26/2020 |
15.0.2 | 31,978 | 1/20/2020 |
15.0.1 | 4,438 | 1/10/2020 |
15.0.0 | 3,976 | 12/17/2019 |
14.9.1 | 1,457 | 11/30/2019 |
14.9.0 | 835 | 11/29/2019 |
14.8.1 | 4,544 | 11/26/2019 |
14.8.0 | 2,222 | 11/20/2019 |
14.7.0 | 20,705 | 10/9/2019 |
14.6.6 | 884 | 10/8/2019 |
14.6.5 | 38,742 | 9/27/2019 |
14.6.4 | 1,192 | 9/21/2019 |
14.6.3 | 7,732 | 8/12/2019 |
14.6.2 | 1,269 | 8/3/2019 |
14.6.1 | 913 | 8/3/2019 |
14.6.0 | 1,333 | 7/26/2019 |
14.5.7 | 3,281 | 7/18/2019 |
14.5.6 | 6,037 | 7/10/2019 |
14.5.5 | 1,474 | 7/1/2019 |
14.5.4 | 6,024 | 6/17/2019 |
14.5.3 | 8,288 | 6/5/2019 |
14.5.2 | 1,030 | 5/30/2019 |
14.5.1 | 888 | 5/28/2019 |
14.5.0 | 3,929 | 5/24/2019 |
14.4.0 | 1,720 | 5/22/2019 |
14.3.4 | 1,441 | 5/14/2019 |
14.3.3 | 1,132 | 5/9/2019 |
14.3.2 | 1,107 | 4/30/2019 |
14.3.1 | 1,358 | 4/27/2019 |
14.3.0 | 1,023 | 4/24/2019 |
14.2.3 | 1,001 | 4/17/2019 |
14.2.2 | 970 | 4/10/2019 |
14.2.1 | 1,832 | 4/5/2019 |
14.2.0 | 2,570 | 3/16/2019 |
14.1.1 | 1,268 | 3/8/2019 |
14.1.0 | 2,080 | 2/11/2019 |
14.0.4 | 1,415 | 1/31/2019 |
14.0.3 | 1,506 | 1/22/2019 |
14.0.2 | 17,120 | 12/15/2018 |
14.0.1 | 2,167 | 11/29/2018 |
14.0.0 | 3,815 | 11/19/2018 |
13.3.0 | 1,213 | 11/16/2018 |
13.2.2 | 1,144 | 11/15/2018 |
13.2.1 | 1,186 | 11/13/2018 |
13.2.0 | 2,048 | 10/31/2018 |
13.1.5 | 1,136 | 10/31/2018 |
13.1.4 | 1,197 | 10/25/2018 |
13.1.3 | 1,183 | 10/18/2018 |
13.1.2 | 3,729 | 9/12/2018 |
13.1.1 | 2,455 | 9/11/2018 |
13.1.0 | 1,172 | 9/11/2018 |
13.0.0 | 8,985 | 8/29/2018 |
12.3.6 | 1,251 | 8/29/2018 |
12.3.5 | 1,339 | 8/22/2018 |
12.3.4 | 1,169 | 8/21/2018 |
12.3.3 | 25,939 | 8/21/2018 |
12.3.2 | 1,197 | 8/20/2018 |
12.3.1 | 1,218 | 8/20/2018 |
12.3.0 | 1,160 | 8/20/2018 |
12.2.2 | 1,269 | 8/15/2018 |
12.2.1 | 1,262 | 8/9/2018 |
12.2.0 | 1,249 | 8/8/2018 |
12.1.11 | 1,246 | 7/30/2018 |
12.1.10 | 2,816 | 7/20/2018 |
12.1.9 | 1,337 | 7/10/2018 |
12.1.8 | 1,451 | 7/2/2018 |
12.1.7 | 5,334 | 6/7/2018 |
12.1.6 | 5,232 | 6/4/2018 |
12.1.5 | 1,400 | 6/2/2018 |
12.1.4 | 1,463 | 5/25/2018 |
12.1.3 | 2,147 | 5/16/2018 |
12.1.2 | 1,314 | 5/15/2018 |
12.1.1 | 1,397 | 5/14/2018 |
12.1.0 | 1,336 | 5/9/2018 |
12.0.7 | 1,353 | 5/5/2018 |
12.0.6 | 1,491 | 5/4/2018 |
12.0.5 | 1,501 | 5/3/2018 |
12.0.4 | 1,453 | 4/30/2018 |
12.0.3 | 1,451 | 4/30/2018 |
12.0.2 | 1,332 | 4/27/2018 |
12.0.1 | 1,619 | 4/25/2018 |
12.0.0 | 1,296 | 4/22/2018 |
11.2.0 | 7,966 | 4/11/2018 |
11.1.0 | 3,463 | 4/8/2018 |
11.0.8 | 1,452 | 3/26/2018 |
11.0.7 | 1,367 | 3/20/2018 |
11.0.6 | 4,986 | 3/7/2018 |
11.0.5 | 1,491 | 2/22/2018 |
11.0.4 | 1,504 | 2/14/2018 |
11.0.3 | 1,544 | 2/12/2018 |
11.0.2 | 1,377 | 2/9/2018 |
11.0.1 | 2,448 | 1/29/2018 |
11.0.0 | 3,120 | 1/15/2018 |
10.0.3 | 3,214 | 12/29/2017 |
10.0.2 | 1,323 | 12/26/2017 |
10.0.1 | 1,639 | 12/18/2017 |
10.0.0 | 1,287 | 12/18/2017 |
9.3.0 | 1,447 | 12/17/2017 |
9.2.0 | 1,251 | 12/17/2017 |
9.1.3 | 1,559 | 12/5/2017 |
9.1.2 | 1,615 | 11/27/2017 |
9.1.1 | 2,569 | 11/21/2017 |
9.1.0 | 1,254 | 11/21/2017 |
9.0.1 | 1,324 | 11/11/2017 |
9.0.0 | 1,314 | 11/10/2017 |
8.7.0 | 1,330 | 11/9/2017 |
8.6.0 | 1,326 | 11/9/2017 |
8.5.0 | 4,841 | 10/3/2017 |
8.4.0 | 1,229 | 10/3/2017 |
8.3.1 | 1,587 | 9/8/2017 |
8.3.0 | 1,277 | 9/8/2017 |
8.2.0 | 1,358 | 9/4/2017 |
8.1.0 | 1,471 | 8/22/2017 |
8.0.0 | 1,504 | 8/19/2017 |
7.1.3 | 1,489 | 8/14/2017 |
7.1.2 | 1,352 | 8/2/2017 |
7.1.1 | 1,355 | 7/26/2017 |
7.1.0 | 7,256 | 7/5/2017 |
7.0.9 | 1,479 | 6/28/2017 |
7.0.8 | 1,382 | 6/19/2017 |
7.0.6 | 15,620 | 4/7/2017 |
7.0.5 | 1,647 | 3/21/2017 |
7.0.4 | 1,393 | 3/21/2017 |
7.0.3 | 1,741 | 3/20/2017 |
7.0.2 | 1,420 | 3/13/2017 |
7.0.0 | 1,776 | 3/1/2017 |
6.2.0 | 1,467 | 2/25/2017 |
6.1.0 | 1,653 | 2/14/2017 |
6.0.0 | 1,346 | 2/9/2017 |
5.3.0 | 1,385 | 2/5/2017 |
5.2.0 | 1,513 | 1/26/2017 |
5.1.0 | 1,286 | 1/19/2017 |
5.0.0 | 1,334 | 1/7/2017 |
4.11.0 | 1,286 | 1/5/2017 |
4.10.0 | 1,295 | 12/31/2016 |
4.9.0 | 1,227 | 12/26/2016 |
4.8.0 | 1,446 | 12/17/2016 |
4.7.0 | 1,300 | 12/8/2016 |
4.6.5 | 1,284 | 12/4/2016 |
4.6.4 | 1,305 | 11/25/2016 |
4.6.2 | 2,320 | 11/18/2016 |
4.6.1 | 1,182 | 11/15/2016 |
4.6.0 | 1,262 | 11/11/2016 |
4.5.9 | 1,621 | 11/2/2016 |
4.5.8 | 1,309 | 11/2/2016 |
4.5.7 | 1,319 | 10/26/2016 |
4.5.6 | 1,255 | 10/6/2016 |
4.5.5 | 1,228 | 10/3/2016 |
4.5.4 | 1,224 | 10/2/2016 |
4.5.3 | 1,231 | 9/30/2016 |
4.5.2 | 1,258 | 9/28/2016 |
4.5.1 | 1,210 | 9/28/2016 |
4.5.0 | 1,268 | 9/28/2016 |
4.4.0 | 1,376 | 9/23/2016 |
4.3.0 | 1,385 | 9/22/2016 |
4.2.0 | 1,626 | 9/19/2016 |
4.1.0 | 1,243 | 9/13/2016 |
4.0.1 | 1,218 | 9/9/2016 |
4.0.0 | 1,260 | 9/9/2016 |
3.6.0 | 1,267 | 9/7/2016 |
3.4.0 | 1,254 | 9/7/2016 |
3.3.0 | 1,246 | 9/4/2016 |
3.2.0 | 1,259 | 9/3/2016 |
3.1.0 | 1,257 | 9/2/2016 |
3.0.0 | 1,553 | 8/31/2016 |
2.5.0 | 1,278 | 8/27/2016 |
2.4.0 | 1,865 | 8/26/2016 |