Monday, August 31, 2015

Umbraco errorlogging with Loggly

Service

At a client I'm currently working at we use GrayLog as our default logging system. This is an open source log management tool that offers a lot of features but for me has one major bottleneck. It requires you to setup a (virtual) server to host this service. While that's perfectly fine for bigger project, it's rather unachievable for little project or proof of concepts that demand centralized logging.

For those small project I wanted to investigate an alternative. I've selected Loggly for my test. This is a commercial cloud log management service that offers a free account that is limited to 200mb a day and 7-day retention. That's fine for me, let's integrate!

NuGet package

 I started this test by downloading Umbraco 7.3.0RC since this version will be released very soon now. As a second package I installed the Loggly log4net package that offers a Log4Net appender that will send out the errormesages to Loggly.

Finished !

Except that Umbraco uses an unsigned version of log4net 1.2.11.0 and Loggly requires a signed 1.2.13.0 version. This would be solvable using assembly binding redirect in the web.config if the appender would be compatible with log4net, but that's not the case. Umbraco will solve this in version 8 due to breaking changes (U4-1324).

Second try

The easiest way of fixing this issue was to download the Loggly appender sources that are available at GitHub and build this solution with the log4net (and Newtonsoft.Json) assemblies referenced from the Umbraco solution. There is only one incompatibility to get rid of. In log4net version 1.2.11.0 the threadcontext property keys are not available yet, but since Umbraco also cannot access them I just disable this bit of logging all the way.






After this I referenced the newly build appender to my Umbraco solution and added the configuration to the default log4net.config

<?xml version="1.0"?>
<log4net>
  
  <root>
    <priority value="DEBUG"/>
    <appender-ref ref="AsynchronousLog4NetAppender" />
    <appender-ref ref="LogglyAppender" />
  </root>

  <appender name="rollingFile" type="log4net.Appender.RollingFileAppender">
    <file value="App_Data\Logs\UmbracoTraceLog.txt" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <maximumFileSize value="5MB" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
    </layout>
    <encoding value="utf-8" />
  </appender>

  <appender name="LogglyAppender" type="log4net.loggly.LogglyAppender, log4net-loggly">
    <rootUrl value="http://logs-01.loggly.com/" />
    <inputKey value="[your token]" />
    <tag value="log4net" />
  </appender>

  <appender name="AsynchronousLog4NetAppender" type="Umbraco.Core.Logging.ParallelForwardingAppender,Umbraco.Core">
    <appender-ref ref="rollingFile" />
  </appender>

  <!--Here you can change the way logging works for certain namespaces  -->

  <logger name="NHibernate">
    <level value="WARN" />
  </logger>
  
</log4net>

And voila, we're logging to Loggly !!

Loggly

Let's check it out and add a dummy exception to the master view. After logging into Loggly I can now see my error messages (beside all the other messages within my defined log level of course).




Friday, June 19, 2015

Codegarden 15 blues...


Wikipedia:
Codegarden Blues:
The vacuum Umbraco Codegarden attendees experience starting right after the event. This feeling can last until the purchase of a ticket for the next Codegarden.




There you have it. Codegarden 2015 is over and we all have the blues. Our usual work has taken over again, deadlines to catch, bugs to solve,... Then again, we met a lot of interesting people and captured loads of teasers that we will try look into asap. Let's look back at this last edition...


Start

It kind of started by the end of March when we (my colleague Jan Vanuytrecht and myself) submitted our session proposal regarding the project we're working on at the moment. We titled our session 'We want a corporate Umbraco platform! Errr.. Sure!' and wanted to share our story with the community on how we solved some key aspects we were dealing with. Soon we received an email from Tim (HQ) saying that our session was approved. Wow, so cool.

The preparation of the session did take a huge amount of effort, of course right in the middle of major deadlines. Starting will full-text slides and ended up after several iterations with visual slides with almost no text at all. This was our first time presenting at such a big event, exiting times :-) Covering a big project like we intended to do brought us to a wide range of topics using a helicopter view. We might have been a little to ambitious in this case and learned that it probably could offer more value with less but more detailed topics, more on this later in this post. Nonetheless we ended up with a very good deal of mind sharing during the 3 Codegarden days, high five to the community!




Future

Exiting times ahead of us offering a lot of cool stuff to look out for. The new api, load balancing, umbraco.com release. On that last topic I did understand during open space that eventually this will enable the open sourcing of Courier. This would enable great improvement being introduced by the community. I like the focus on the core itself.


Bingo

Could write a lot of great things about the Bingo, but...
What happens at the Bingo stays at the Bingo :-)))


Open space

An interesting topic I attended during the open spaces was about strong typed models and on a broader level the choice of an architecture. A project architecture that includes design decisions supported by a combination of Umbraco packages. Certainly for newbies it's not quite clear how to set up an Umbraco project, loads of choices to make. I suggested a place on Our for documenting architectural designs, each explaining why certain concepts and/or packages were chosen. I would find that very informative myself.

At the last day during the open space wrap-up one of the conclusions about this Codegarden was that there was a lack of in-depth technical sessions this year. This seemed to be true to me too, also our session could have a technical deep dive but we had no clue upfront. Since search seemed a hot topic our Solr integration would be a nice topic. To fill the gap a bit we will write a few articles on this subject in the next few weeks and months.


People

CG15-Congratulations-2004
Picture made by Douglas Robar
Codegarden is all about people and networking. Despite the fact that I'm a rather introvert person myself I find it very easy to get in contact with a huge amount of other attendees. It's such a welcoming community and sharing is key. Love it,

Another example is the picture on the left taken by Douglas Robar after Niels ordered a big banner with express delivery wishing my collegua Jan Vanuytrecht all the luck with his new born son, Viktor. How great and heartwarming is that!


Next

Codegarden left me with a trello board full of todo's.
I'll just end this post and start with my first todo:
use Umbraco + Articulate for my blog, I don't like Blogger :-)

Cheers,
Bart

Monday, April 28, 2014

Deep page links with an Umbraco widget structure

Last Friday I attended the Umbraco BE Festival organised by the Belgian Umbraco User Group with a few colleagues in Antwerp. Having such an event hosted next door is a real luxury so we couldn't resist joining the enthusiastic community.

During his outstanding 'Umbraco news, it's not only Belle' session Stephane Gay gave us some more insights into Umbraco 7 core, namely the url segment and url providers, the content finders.

EUREKA !

Interestingly enough the url provider was a perfect match for our current Umbraco project where we are creating a widget structure. For this setup we wanted to support deep page links so a backoffice user can create a link using a link picker to any content, being a page or child widget. A link to a widget should result into a page link with an anchor to this specific widget. Of course the view will automatically create an anchor element per widget while rendering the content.

So, while we were looking into a manual url resolving within the page controller, we now know about url providers and can utilize this feature to have our deep links propagated throughout the whole Umbraco system.

So we first define our widget url provider, inheriting from the DefaultUrlProvider this is easy.
1:    public class WidgetUrlProvider : DefaultUrlProvider  
2:    {  
3:      readonly IUrlProvider _provider = new DefaultUrlProvider();  
4:      public override string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)  
5:      {  
6:        var content = umbracoContext.ContentCache.GetById(id);  
7:        if (content.DocumentTypeAlias != ProjectSettings.WidgetAlias) return null;  
8:        var parentPage = content.Ancestors(ProjectSettings.PageAlias).First();  
9:        var widgetUrl = String.Format("{0}#{1}", parentPage.Url, content.Name);  
10:        return widgetUrl;  
11:      }  
12:    }  

We can now override the GetUrl method and insert our custom url builder logic. We want to activate this provider only to generate url's for out widgets, so we check if the current document type is a widget. Then we retrieve the parent page and get it's url so we can suffix the widget node name as an anchor.

All we have to do now is letting Umbraco know we have a url provider. We can hook into the Umbraco startup process by creating a class that inherits from ApplicationEventHandler so we can override the ApplicationStarting method. In this method we can add our custom url provider to the list.
1:    protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) 
2:    {  
3:      base.ApplicationStarting(umbracoApplication, applicationContext); 
4:      UrlProviderResolver.Current.InsertType<WidgetUrlProvider>();
5:    }  

The result is that every link to this widget is created our prefered way now, in the Umbraco Backoffice,


and if we create a page template to present our page


and call our Page1 we get the same link rendered in the browser if we create a link to a widget in a richtextbox for example


Now we have our custom url's activated in the backoffice as well as the template rendering.
Nice !!

Of course this sample is very simplified for sake of the demo. Our widget system is quiet more enhanced then this :-)