This is my second post of me getting familiar with Prefix from Stackify. This time I will use Prefix in a simple ASP.Net WebAPI (using OWIN) hosted in IIS-Express. I will also make it use MongoDB and hook in NLog so that we can see how easy that is.
If you want to read the first post, then head over here: GHOST_URL/stackify-prefix-at-a-glance/
There's a repository on GitHub, that you can explore or use.
Getting setup
This was covered in the previous post, but basically:
- Get the installer and install it
- Enable the profiler
- Enable it in IIS-Express
The third step is done by updating: [your src folder]\.vs\config\applicationhost.config
.
All you need to do is to add the module registration as specified in the docs.
<system.webServer>
<modules>
...
<add name="PrefixModule_Net40" type="StackifyHttpTracer.StackifyHttpModule,StackifyHttpTracer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=93c44ce23f2048dd" preCondition="managedHandler,runtimeVersionv4.0" />
</modules>
</system.webServer>
Then restart Visual Studio and fire up e.g. ASP.Net MVC or an WebAPI and "Voilà! It works!".
The Code
Remember, this is just some demo code. First lets get MongoDb and NLog into the project
install-package mongodb.driver
install-package nlog.config
Then lets have something that stores and returns some orders
public class Order
{
public Guid Id { get; set; }
public string Customer { get; set; }
public decimal Amount { get; set; }
}
public static class Orders
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly IMongoCollection<Order> OrdersCollection;
static Orders()
{
Logger.Info("Bootstrapping Orders");
var client = new MongoClient("mongodb://development:27017");
var database = client.GetDatabase("ordering");
OrdersCollection = database.GetCollection<Order>("orders");
}
public static async Task<Order> StoreAsync(Order order)
{
Logger.Trace("Storing new Order {0}", order.Id);
await OrdersCollection
.InsertOneAsync(order)
.ConfigureAwait(false);
return order;
}
public static async Task<List<Order>> GetAsync()
{
Logger.Trace("Getting orders");
return await OrdersCollection
.Find(o => true)
.ToListAsync()
.ConfigureAwait(false);
}
}
Then a simple ApiController
[RoutePrefix("api/orders")]
public class OrdersController : ApiController
{
[Route]
[HttpPost]
public async Task<Order> PostAsync()
{
var order = new Order
{
Id = Guid.NewGuid(),
Amount = new Random().Next(1000, 10000) / 100M,
Customer = "Joe"
};
await Orders.StoreAsync(order).ConfigureAwait(false);
return order;
}
[Route]
[HttpGet]
public async Task<List<Order>> GetAsync()
{
return await Orders.GetAsync().ConfigureAwait(false);
}
}
NLog
While it will detect MongoDB calls automatically, it will not pick up and parse NLog logging calls automatically. To do that, you need to install a NuGet package (offical docs)
install-package stackifylib.nLog
During installation you get prompted for an API-key
. You can leave that blank.
It will insert some code in web.config
. Which I removed. The only stuff that I kept was the app settings
<appSettings>
<add key="Stackify.ApiKey" value="" />
<add key="Stackify.AppName" value="Test"/>
<add key="Stackify.Environment" value="Your Environment"/>
</appSettings>
Instead, I hooked it in using NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log" >
<extensions>
<add assembly="StackifyLib.nLog" />
</extensions>
<targets>
<target name="stackify" type="StackifyTarget" />
<target xsi:type="File"
name="f"
fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules>
<logger name="*"
minlevel="Trace"
writeTo="stackify" />
<logger name="*"
minlevel="Trace"
writeTo="f" />
</rules>
</nlog>
Finally, the Startup
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
}
The Result
If you start issuing some HTTP-requests:
POST http://localhost:50294/api/orders
GET http://localhost:50294/api/orders
you should start seeing data coming into Prefix.
It's that easy. You can of course drill down and see modules etc. and the response data etc.
Findings
Running the same request many times, via e.g Postman or curl, Prefix misses to render a request every now and then. This gets even more obvious when you hook in e.g. NLog and the Stackify target, and then compare the output in Prefix and NLog.
This might be by design, that it samples, but does that make sense for a profiler tool?
If you clear the list within Prefix, and then hit refresh after being prompted with "Create some traffic to your local web server", the list is filled with the cleared requests.
Awesome response by Stackify
In my previous post, I encountered that Prefix was generating network traffic out from my computer. I asked Stackify about it, and they answered and immediately seem to have written a document about the data policy: http://support.stackify.com/hc/en-us/articles/208215323-Prefix-Data-Collection-Policy
Summary
Remember. It is a "web" profiler tool, in the sense that it hooks into the HTTP-request/response pipeline. So e.g. static bootstrapping in static classes is not profiled and the log calls in there does not get rendered in the UI.
//Daniel