public virtual async Task <long[]> Counts(
            string eventName,
            DateTime startTimestamp,
            DateTime endTimestamp,
            ActivityDrilldown drilldown)
        {
            Validation.ValidateEventName(eventName);

            var dates = startTimestamp.Range(endTimestamp, drilldown);
            var key   = GenerateKey(eventName, drilldown.ToString());

            var fields = dates.Select(d =>
                                      GenerateTimeframeFields(drilldown, d)
                                      .ElementAt((int)drilldown))
                         .ToArray();

            string[] values;

            using (var connection = await ConnectionFactories.Open())
            {
                values = await connection.Hashes.GetString(
                    Settings.Db,
                    key,
                    fields);
            }

            var result = values.Select(v =>
                                       string.IsNullOrWhiteSpace(v) ? 0L : long.Parse(v))
                         .ToArray();

            return(result);
        }
        public virtual async Task <long> Track(
            string eventName,
            ActivityDrilldown drilldown,
            DateTime timestamp,
            bool publishable)
        {
            Validation.ValidateEventName(eventName);

            var key       = GenerateKey(eventName, drilldown.ToString());
            var eventsKey = GenerateKey();
            var fields    = GenerateTimeframeFields(drilldown, timestamp).ToList();
            var db        = Settings.Db;

            using (var connection = await ConnectionFactories.Open())
            {
                await connection.Sets.Add(db, eventsKey, eventName);

                var tasks = fields
                            .Select(field => connection.Hashes
                                    .Increment(db, key, field))
                            .ToList();

                var counts = await Task.WhenAll(tasks);

                var count = counts.ElementAt((int)drilldown);

                if (!publishable)
                {
                    return(count);
                }

                var channel = eventsKey +
                              Settings.KeySeparator +
                              eventName.ToUpperInvariant();

                var payload = new EventActivitySubscriptionInfo
                {
                    EventName = eventName,
                    Timestamp = timestamp,
                    Drilldown = drilldown,
                    Count     = counts.ElementAt((int)drilldown)
                }.Serialize();

                await connection.Publish(channel, payload);

                return(count);
            }
        }