Using influxDB with Sitecore Part 2

This is a continuation of Part 1 where I go over how to setup influxdb to monitor Solr. If you haven’t read it and are looking for installation guides for influx, check out part 1 here

In this PART 2 I want to setup some basic statistics for when visitors hit a 404 or a 500 page and showcase the influxDB C# client. We’ll see how we can present the data in InfluxDB at the end. To try and cut down this post a bit I’ll make some assumptions: That you can setup your own pipelines and processors to start the execution of your code at the correct place.

The influxDB C# client only supports .NET Core so you can setup a separate API service that your Sitecore application can use to Write and Get the data.

  1. I’ll show how we can write data to influxDB through code.
  2. We’ll look at getting data from influxDB through code.


1. Write data to InfluxDB

Here we can write some data to our influxDB bucket by code, keeping it simple:

using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core;

...

const string token = "<TOKEN>";
const string bucket = "errorbucket";
const string org = "myOrg";

var client = InfluxDBClientFactory.Create("http://localhost:8086", token);

var 500error = new ErrorPage { Type = "500", Hit = 1, Time = DateTime.UtcNow };
var 404error = new ErrorPage { Type = "404", Hit = 1, Time = DateTime.UtcNow };

using (var writeApi = client.GetWriteApi())
{
   if(errorCause == 500)
      writeApi.WriteMeasurement(500error, WritePrecision.Ns, bucket, org);
    
   if(errorCause == 404)
      writeApi.WriteMeasurement(404error, WritePrecision.Ns, bucket, org);
}

[Measurement("error_page")]
public class ErrorPage
{
    [Column("type", IsTag = true)] public string Type { get; set; }
    [Column("hit")] public int? Hit { get; set; }
    [Column(IsTimestamp = true)] public DateTime Time { get; set; }
}

Now we got some data in InfluxDB that we can show in a dashboard ( see Part 1 on how to setup dashboard)

Sample data

2. Get – Query data

A simple method to get the hit count for 404 pages. This will simply return 31 if we go by the data from above. Change the “type” to 500 to get the count for that one etc.

public async Task<int> Get404Hits()
{
    var fluxQuery = "from(bucket: \"errorbucket\") " +
                    "|> range(start: -1d)" +
                    "|> filter(fn: (r) => r[\"_measurement\"] == \"error_page\")" +
                    "|> filter(fn: (r) => r[\"_field\"] == \"hit\")" +
                    "|> filter(fn: (r) => r[\"type\"] == \"404\")" +
                    "|> cumulativeSum(columns: [\"_value\"])";

    var result = await client.GetQueryApi().QueryAsync<int>(fluxQuery, org);

    return result.Count;
}

Now you can write and query data in C# with InfluxDB.
You can for example create your own graph to present inside Sitecore or use the dashboard in InfluxDB.

Thanks for reading and hope you get some usage with InfluxDB. I’m still learning and I see a lot of fun stuff ahead with this tool.

Get items from Bucket in Sitecore

I need to get items from a big bucket.
For best performance you should get the items through Sitecore ContentSearch.

Here I have some example code how to get a selection of items from a bucket.
Let’s say I want to get items that has a specific Tag on a field, which in this case is a string type field. (You can of course change the queryable to whatever you like)

List<Item> ResultsItems = new List<Item>();
IIndexable index = new SitecoreIndexableItem(bucketItem);

using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
{
   var results = 
     context.GetQueryable<T>().Where(x => x.TagFieldName.Equals("TagName"))).GetResults();
   
   foreach (var result in results)
   {
     Item item = result.Document.GetItem();
     if(item !=null)
     {
       ResultsItems.Add(item);
     }
   }
}

Now ResultsItems are filled with the item context of all the children of the bucket.

Note: I’m showing the code for demonstration purpose. Beware of potentially calling a GetItem() on potential thousands of items.
I would also recommend selecting the fields you are after with .Select(i => new { i.FieldA, i.FieldB}) (read more here) so that the query gets smaller.

Sitecore installation setup UI

Just had to make a quick post about this because apparently I’ve been living under a rock.
I’ve used SIF and setting up configs on my own every time I’ve setup a new sitecore instance.
Which now in hindsight has been a giving lesson to learn the basics.

I mean if you’re just after a quick install for an empty Sitecore instance this is golden.
So this is for all others that have missed this too.


You can download this at the normal Sitecore download section: https://dev.sitecore.net/Downloads/Sitecore_Experience_Platform/102/Sitecore_Experience_Platform_102


Sitecore shutting down – initialization error

The problem: All I could see in the log file was that error message “sitecore shutting down – initialization error“. This didn’t tell me much of where the issue was coming from except when Sitecore is spinning up.

So I took a look in the Event viewer to check out any logs there.
Open “Event Viewer” by clicking the “Start” button. Click “Control Panel” > “System and Security” > “Administrative Tools”, and then double-click “Event Viewer”.

Go to Windows Logs -> Application and you’ll see the latest log inputs at the top.

Click it and read the details. There I saw my problem.

It was a config file that was hooking into the initialize pipeline and had a faulty dependency. Whops. Fix that and bada boom, Sitecore starts to spin up again.

Add custom buttons to Dashboard/Launchpad

A neat way to execute or show some custom functionalities is to create a custom button for the Sitecore Dashboard/Launchpad (whatever you call it, I say Dashboard).
This is very simple and you can easily make the button either for example

a) open an aspx
b) show custom views
c) make an API request to one of your controller actions

Sitecore dashboard
Here i’ve added “My button” to the Control Panel section

Step 1

Switch to Core database by going to the Desktop view and in the lower right corner switch database. (Or enter the querystring &sc_content=core)
Then enter the Content Editor

Step 2

Locate /sitecore/client/Applications/Launchpad/PageSettings/Buttons and you will find the sections corresponding to the Dashboard/Launchpad

Step 3

Choose what section you want to put your button in and right-click the item (Tools = Control Panel) and add a new Launchpad-button

Step 4

Fill in the button as you want.
Text: The text for the button on the Dashboard/Launchpad
Icon: Icon for the button
Link: You can link directly to a Sitecore Item or a controller action within the sitecore api as i’ve done. (or your own api)
OpenNewTab: Clicking the button opens it in a new tab.
OpenIframe: Clicking the buttons opens an iframe.
PathResolver: Namespace and dll name

That’s it. It should now show up on the Dashboard/Launchpad

Replace non-english characters

I needed to replace swedish characters from string without removing the character for itemname.

With Sitecore you can use ItemUtil.ProposeValidItemName() but it removes the invalid characters.
I have a text like “Flöde” and I want it to be “Flode” and not “Flde” like Sitecores ItemUtil does.

Then I can use the following code:

byte[] b = Encoding.GetEncoding(1251).GetBytes("Flöde/");
string output = Encoding.ASCII.GetString(b);

string validItemName = ItemUtil.ProposeValidItemName(output);

________________________
output: "Flode/"
validItemName: "Flode"

The ItemUtil.ProposeValidItemName will give you a valid item name for Sitecore.
The string output would still contain possible invalid special characters that you don’t allow in the Sitecore config setting ItemNameValidation regex.

Custom caching with Sitecore Cache

Performance is key. We have all know this. Customers has very high expectations on fast solutions. And this is where caching is king.

There are many caching soultions out there today, like Reddis cache. You can also build your own layer if you’d like. Or you can use Sitecores.

Sitecore has their own caching framework that is used for Sitecore to get data faster. This can also be used for custom caches. So you can cache something simple as a string or even anonymous objects.

There are two types of cache you can use for customcaching.

Sitecore.Caching.CustomCache<string> and Sitecore.Caching.Generics.Cache<T>. One takes a string and one takes an object type.

Sample code

   var mycache = new Sitecore.Caching.Cache("test cache", 1024);
   mycache.Add("key", "data");

   var myType = new Type {Id = 1, Name = "Test"};
   mycache.Add("type", myType);

   //Get the value based on key
   var value = mycache.GetValue("type");

Read more:

http://sitecore-community.github.io/docs/documentation/Sitecore%20Fundamentals/Caching/

Sitecore Solr – Select specific fields with LINQ to Sitecore

If you’re expecting a lot of results from a Solr query, it can be quite a perfomance hit.
If you then only really need 1 or 2 fields from the document, there is a neat way with LINQ to Sitecore to select only the fields you need.

var items = searchContext.GetQueryable<BaseSearchResultItem>().Where(i => i.TemplateId == <templateid>).Select(i => new { i.Heading, i.ItemId }).ToList();

By using the .Select() you can specify which fields you want to get from the document.
This query will result in a Solr query like following:

?q=(_template:(<templateId>))&start=0&rows=1000000 &fl=headingFieldName,_uniqueid,_datasource&fq=_indexname:(sitecore_master_index)

In Solr it’s called “Field List” or “fl” and in Solr UI you can test the effect before compiling your code like this, which I prefer to do.

Good luck with your Sitecore Search.

Sitecore xConnect error GetEntityOperation

This error message caught my eye on xConnect in Sitecore 9.3, which looked like this.

"[Error] Sitecore.XConnect.Operations.GetEntityOperation`1[Sitecore.XConnect.DeviceProfile]: Sitecore.Xdb.Collection.Failures.DataProviderException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception: The system cannot find the file specified"

This issue was because of Xdb had wrong ServerName in the [*.Collection.ShardMapManager] database.


The database and table “[*.Collection.ShardMapManager].[__ShardManagement].[ShardsGlobal]” that contains [ServerName] and [DatabaseName] columns. Replace with your ServerName and hopefully this will be the issue in your case.

Hope this helps if you get a similar error.

Sitecore Solr Sort Alphabetically

Just a short and quick blogpost. I got an issue with my alphabetically sort.
This was because my field was tokenized and of type text in Solr. So I had to make the field Untokenized and returnType string. Fixed!

With Sitecore you can pretty easy sort by Ascending or Descending with LINQ to Sitecore
Just write an OrderBy or OrderByDescending with your field like so:

switch (direction)
{
  case SearchOrderDirection.Ascending:
    return queryable.OrderBy(i => i.Title);
  case SearchOrderDirection.Descending:
  default:
    return queryable.OrderByDescending(i => i.Title);
}

REMINDER: The field should be UNTOKENIZED and returnType string.