Archive

Posts Tagged ‘MongoDB’

Launch Mongo DB with Sitecore Pipelines

01/10/2014 2 comments

My  colleague Brian Pedersen recently wrote at blog post about setting up MongoDB and starting it up with a simple bat-file read it here

http://briancaos.wordpress.com/2014/10/01/sitecore-and-xdb-setting-up-mongodb-on-your-developer-machine/

Combine the first step “download” mongo with starting a process as my other colleague Anders Laub showed how to do in his crush png post here http://laubplusco.net/crush-png-in-sitecore/

 

Then you have a pipeline that can start mongo if it isn’t running.

First lets create a new custom pipeline to start a mongo instance if none  is running

First the new “startmongodb” pipeline

<startmongodb>
  <processor type="Mongo.PingMongoDB, Mongo" />
  <processor type="Mongo.StartMongoDB, Mongo" />
</startmongodb>

  Replace string constant with more generic method, First a processor that test to see if mongo is allready running.

   public class PingMongoDB
    {
        public void Process(PipelineArgs args)
        {
            Log.Audit("Pinging Mongo", this);
            //Replace with connectionstring from config file
            var client = new MongoClient("mongodb://localhost");

           var server = client.GetServer();

            try
            {
              server.Ping();
              Log.Audit("Mongo Allready running", this);
              args.AbortPipeline();
            }
            catch (Exception)
            {
                Log.Audit("Mongo Not Running", this);
            }
        }
    }

 Now to the start mongo processor 

    public class StartMongoDB
    {
        public void Process(PipelineArgs args)
        {
            var startInfo = new ProcessStartInfo
            {
                CreateNoWindow = true,
                UseShellExecute = false,
                //Replace with path to  your mongo
                FileName = "D:\\MongoDB\\bin\\mongod.exe",
              //Replace with path to  your mongo datadrive
                Arguments = @"--dbpath sc75rev140429\Databases\MongoDBData",
                WindowStyle = ProcessWindowStyle.Hidden
            };
            try
            {
                Log.Audit("Trying to start mongo",this);
                using (var exeProcess = System.Diagnostics.Process.Start(startInfo))
                {
                    exeProcess.WaitForExit(50);
                }
                Log.Audit("Mongo started", this);
            }
            catch (Exception exception)
            {
                Log.Error("Could not start mongo", exception, this);
            }
        }
    }

 

Finally we need to run the “startmongodb” pipeline when Sitecore Starts/Initialize so in

the initialize pipeline and at the end add 

<processor type="Mongo.RunMongoPipeline, Mongo" />

code for this simple processor

public class RunMongoPipeline
    {
        public void Process(PipelineArgs arg)
        {
            CorePipeline.Run("startmongodb",new PipelineArgs());
        }
    }

From the log we can now see if mongo isn’t runnnig and was started also there is now warnings in the log :
INFO AUDIT (default\Anonymous): Mongo Not Running
INFO AUDIT (default\Anonymous): Trying to start mongo
INFO AUDIT (default\Anonymous): Mongo started

so the follwing isn’t seen in the log which it would be if mongo wasn’t running

ERROR MongoDbDictionary.Store() has failed.
Exception: Sitecore.Analytics.DataAccess.DatabaseNotAvailableException
Message: Database not available
Source: Sitecore.Analytics.MongoDB
   at Sitecore.Analytics.Data.DataAccess.MongoDb.MongoDbCollection.Execute(Action action, ExceptionBehavior exceptionBehavior)
   at Sitecore.Analytics.Data.DataAccess.MongoDb.MongoDbDictionary.Store(Object value)

What is left now is cleaning the code and use args for supplying the correct values instead of hardcoded strings. This is left as a free of charge  excercise.

Categories: C#, MongoDB, Sitecore Tags: , ,

Storing Sitecore log events in MongoDB

17/06/2014 4 comments

After Sitecore announced the new Sitecore Experience Database (former DMS), which also included a move from a SQL to a NoSQL database, I thought it was about time to give MongoDB a closer look. After reading a lot of related blog post, seeing educational videos and more, I build few demo apps using the MongoDB. But what Ireally wanted to do, was to use Mongo along with Sitecore, and yes i know there exist MongoDB data providers but i really wanted to start  with something more simple, or at least for me as an MongoDB rookie.

So what better then trying to store Sitecore’s Log events in a Mongo database.

First we need to derive from the log4net implementation found in Sitecore.Logging.dll, to build functionality to catch log entries.


public class MongoLogger : AppenderSkeleton
{
  public string ConnectionString { get; set; }
  public string CollectionName { get; set; }
  private MongoRepository _mongoRepository;

  public MongoRepository MongoRepository
  {
   get
     {
      if (_mongoRepository == null)
      {
        _mongoRepository = new MongoRepository(ConnectionString, CollectionName);
      }
      return _mongoRepository;
     }
  }

  protected override void Append(LoggingEvent loggingEvent)
  {
    MongoRepository.Put(loggingEvent);
  }
}

 

As it turns out the LogEvents is easily serialized and deserialized by the Mongo C# driver. I’ve used the offcial MongoCSharprDRiver for this project.
As seen in code above the logger talks with a Data Repository.  So next is the MongoDB repository that handles all calls to the Database.


public class MongoRepository
{
private readonly string _connectionString;
private readonly string _collectionName;

public MongoRepository(string connectionString, string collectionName)
{
_connectionString = connectionString;
_collectionName = collectionName;
UnMapAllMongoIdField();
}

public void UnMapAllMongoIdField()
{
//Only need once per instance

BsonClassMap.RegisterClassMap<T>(cm =>

{
cm.AutoMap();
cm.SetIgnoreExtraElements(true);
});
}

public virtual void Put(LoggingEvent logEntry)
{
Collection.Insert(logEntry);
}

public virtual LoggingEvent GetSingle(Func<LoggingEvent, bool> filter)
{
return Get(filter).FirstOrDefault();
}

public virtual IEnumerable<LoggingEvent> Get(Func<LoggingEvent, bool> filter)
{
return Collection.AsQueryable<LoggingEvent>().Where(filter);
}

private MongoUrl _mongoUrl;
private MongoUrl MongoUrl
{
get { return _mongoUrl ?? (_mongoUrl = MongoUrl.Create(_connectionString)); }
}

private MongoClient _client;
private MongoClient Client
{
get { return _client ?? (_client = new MongoClient(MongoUrl)); }
}

private MongoServer _server;
private MongoServer Server
{
get { return _server ?? (_server = Client.GetServer()); }
}

private MongoDatabase _database;
private MongoDatabase Database
{
get { return _database ?? (_database = Server.GetDatabase(MongoUrl.DatabaseName)); }
}

private MongoCollection<BsonDocument> _collection;
private MongoCollection<BsonDocument> Collection
{
get { return _collection ?? (_collection = Database.GetCollection(_collectionName)); }
}
}

You could off course make the repository more generic but for simplicity it will only handle LogEvents.

Next we need to change the default Logger to use our new Mongo Logger. For this post I will only change the default Logger but you could if you wanted change all the Logger Appenders (SearchLogger, WebDavLogger, CrawlingLoggeror the PublishLogger). In the web.config under the log4net section add a the new log appender we created above like shown below. You can off course change DB-name and collection name as you like.


<appender name="MongoDBAppender" type="SitecoreMongoDBAppender.MongoAppender, SitecoreMongoDBAppender">
<connectionstring value="mongodb://localhost:27017/Logs" />
<collectionname value="log" />
</appender>

and also update the root section to point to long appender


 <root>
 <priority value="INFO" />
 <appender-ref ref="MongoDBAppender" />
 </root>

if you start up Sitecore now you should get entries into the MongoDB

17-06-2014 09-04-32

You could replace all the log appender with the  new MongoLogger . You can if  you want use the different collections or just store each logevent in one big collection. Maybee next one should build a Sitecore Speak application to show the relevant log information, inside Sitecore but that is left for the reader :). The repository allready have Get method, where you can parse in your own linq queries.

 

Categories: .Net, C#, MongoDB, Sitecore Tags: , ,