The Apprenda platform has a solid multi-level and context-aware logging service available to guest apps. Whether the app is a single-tenant public UI, or a complex n-tier distributed app, all app workloads running on "Apprenda proper" have the benefit of using the logging API to capture events into a centralized platform location. Very handy indeed. For more: http://docs.apprenda.com/current/logging
But what about app workloads that run outside of "Apprenda proper", like mobile clients? As application architectures strive towards modernization, mobile clients are becoming more prevalent. Let's look at a method for wrapping the native Apprenda logging API in a custom service to public.y expose its functionality as a nice clean REST API for use by mobile clients.
The REST API Service
Apprenda’s logging API is built into a collection of classes that ship with the Apprenda SDK in the DLL Apprenda.Logging.dll. Ordinarily, a developer references this DLL to access the API functionality within an ASP.NET web app or WCF service that will run on “Apprenda proper”. In the case of mobile clients, we don’t have the luxury of embedding a library to access a native API. Instead, our approach is to build a WCF service that references the Apprenda logging API, and communicate with that web service from the mobile client(s). The great thing about this is that once the logging call reaches our “wrapper” service, all the tenets of the Apprenda logging API hold true – if the logging service is deployed with authentication enabled, then the mobile client will have to send an authentication token (meaning the user has logged in via the mobile app), which means our service will turn around and log to Apprenda’s logging service with all of the contextual information for the authenticated user.
Let’s define our wrapper service contract:
All we’re doing here is mapping our service’s methods to the methods in the Apprenda logging API. We want to be able to log from the mobile clients in any of the platform’s severities, so we expose a method for each. We’re also using the WebInvoke attribute to instruct WCF (and Apprenda) to create the endpoint necessary to reach this service over basic http using REST. We’re taking this approach so that we can call this service from pretty much any mobile client capable of making an HTTP call (Windows Phone, iOS, Android, etc.)
Now, our service implementation:
Here we’ve created a WCF service class that implements our logging wrapper contract. Each method simply receives a message to be logged and uses the Apprenda logging API to drop that message into Apprenda’s centralized log storage. The screenshot show some of the method implementations, some are cut off.
Deployment Options for the API Service
As with any service deployed on Apprenda, we have some deploy-time choices for enhancing the service with platform services:
If we leave these settings alone, then we are creating a web service that is entirely public. It will have a public URL that any client anywhere on the internet can call. If we choose authentication, then the client making the request will have to pass an authentication token, meaning that they will have to have previously authenticated with Apprenda. This is ideal. It also allows the Apprenda logging API to grab contextual information about the user making the call when our wrapper service logs to Apprenda.
Calling the API
I’ll use Fiddler to create HTTP POST requests to the service to illustrate here, but the client might as well be any mobile app capable of making an HTTP request.
In the example above, I simply pointed Fiddler at the URL for my service, set the HTTP Header “Content-Type” to “application/json” and sent a string in the request body. Now, if I’ve selected to have Apprenda require authentication in order to call the logging wrapper service, I will need to send an AuthenticationToken HTTP header as well, which I’d get from logging into the platform during a previous API call. See: http://apprenda.com/blog/general/mobile-development-using-the-apprenda-platform/
Let’s take a look at log results from both scenarios:
Without authentication enabled:
With authentication enabled:
Note that because the user making the log call was authenticated, our logging wrapper service logged to Apprenda with context – the identity of the user. While that little nugget of information is useful in and of itself, it allows us to do something pretty cool using Apprenda’s built-in log overriding mechanism. Since we are now logging with contextual information attached to logs, we can turn the log level UP for this user, while leaving it at a lower level for everyone else. This is especially handy when you have one user whose mobile experience is not working like it should. The following override will set the log level to Debug for that user, allowing us to capture more verbose logs for that user.
In the approach here, we’re not applying overrides or filters on the client. Therefore, ALL logging traffic will be sent from the mobile client to the logging wrapper service. The filtering is done by the Apprenda API usage in that service. Therefore, we’re incurring bandwidth for logging calls that may not actually be stored. One way we might skirt that issue is to add a method to our wrapper service that gets the current platform log level. We can call that method when our mobile app starts up so that we have something to check against before making logging service calls.