Esempio n. 1
0
        const string RowKeyFormat       = "{0}"; // functionInstanceId

        internal static InstanceTableEntity New(FunctionInstanceLogItem item)
        {
            item.Truncate();

            string argumentJson = null;

            if (item.Arguments != null)
            {
                argumentJson = JsonConvert.SerializeObject(item.Arguments);
            }

            return(new InstanceTableEntity
            {
                PartitionKey = PartitionKeyFormat,
                RowKey = RowKeyFunctionInstanceId(item.FunctionInstanceId),

                ParentId = item.ParentId,
                FunctionName = item.FunctionName,
                TriggerReason = item.TriggerReason,
                StartTime = item.StartTime,
                EndTime = item.EndTime,

                RawStatus = item.Status.ToString(),

                LogOutput = item.LogOutput,

                ErrorDetails = item.ErrorDetails,
                ArgumentsJson = argumentJson
            });
        }
        const string RowKeyFormat = "{0}"; // functionInstanceId

        internal static InstanceTableEntity New(FunctionInstanceLogItem item)
        {
            string argumentJson = null;
            if (item.Arguments != null)
            {
                argumentJson = JsonConvert.SerializeObject(item.Arguments);
            } 

            return new InstanceTableEntity
            {
                PartitionKey = PartitionKeyFormat,
                RowKey = RowKeyFunctionInstanceId(item.FunctionInstanceId),

                ParentId = item.ParentId,
                FunctionName = item.FunctionName,
                TriggerReason = item.TriggerReason,
                StartTime = item.StartTime,
                EndTime = item.EndTime,

                RawStatus = item.Status.ToString(),

                LogOutput = item.LogOutput,

                ErrorDetails = item.ErrorDetails,
                ArgumentsJson = argumentJson
            };
        }
Esempio n. 3
0
 /// <summary>
 /// true if this function has completed (either success or failure)
 /// </summary>
 public static bool IsCompleted(this FunctionInstanceLogItem item)
 {
     if (item == null)
     {
         throw new ArgumentNullException("item");
     }
     return(item.EndTime.HasValue);
 }
Esempio n. 4
0
 /// <summary>true if this function succeeded.</summary>
 public static bool IsSucceeded(this FunctionInstanceLogItem item)
 {
     if (item == null)
     {
         throw new ArgumentNullException("item");
     }
     return(item.Status == FunctionInstanceStatus.CompletedSuccess);
 }
        private static void Increment(FunctionInstanceLogItem item, TimelineAggregateEntity x)
        {
            x.TotalRun++;

            if (item.IsSucceeded())
            {
                x.TotalPass++;
            }
            else
            {
                x.TotalFail++;
            }
        }
Esempio n. 6
0
        const string RowKeyFormat       = "{0}-{1:D20}-{2}"; // functionId, timeBucket(descending), salt

        internal static RecentPerFuncEntity New(string containerName, FunctionInstanceLogItem item)
        {
            return(new RecentPerFuncEntity
            {
                PartitionKey = PartitionKeyFormat,
                RowKey = RowKeyTimeStampDescending(item.FunctionId, item.StartTime, item.FunctionInstanceId),
                FunctionName = item.FunctionName,
                DisplayName = item.GetDisplayTitle(),
                FunctionInstanceId = item.FunctionInstanceId.ToString(),
                StartTime = item.StartTime,
                EndTime = item.EndTime,
                RawStatus = item.Status.ToString(),
                ContainerName = containerName
            });
        }
        internal static RecentPerFuncEntity New(string containerName, FunctionInstanceLogItem item)
        {
            return new RecentPerFuncEntity
            {
                PartitionKey = PartitionKeyFormat,
                RowKey = RowKeyTimeStampDescending(item.FunctionName, item.StartTime),

                FunctionName = item.FunctionName,
                DisplayName = item.GetDisplayTitle(),
                FunctionInstanceId = item.FunctionInstanceId.ToString(),
                StartTime = item.StartTime,
                EndTime = item.EndTime,
                RawStatus = item.Status.ToString(),
                ContainerName = containerName
            };
        }
        public async Task AddAsync(FunctionInstanceLogItem item, CancellationToken cancellationToken = default(CancellationToken))
        {
            item.Validate();

            {
                lock (_lock)
                {
                    StartBackgroundFlusher();
                    if (_container == null)
                    {
                        _container = new ContainerActiveLogger(_containerName, _instanceTable);
                    }
                    if (_instanceLogger == null)
                    {
                        int size = GetContainerSize();
                        _instanceLogger = new CloudTableInstanceCountLogger(_containerName, _instanceTable, size);
                    }
                }
                if (item.IsCompleted())
                {
                    _container.Decrement(item.FunctionInstanceId);
                    _instanceLogger.Decrement(item.FunctionInstanceId);
                }
                else
                {
                    _container.Increment(item.FunctionInstanceId);
                    _instanceLogger.Increment(item.FunctionInstanceId);
                }
            }

            lock (_lock)
            {
                if (_seenFunctions.Add(item.FunctionName))
                {
                    _funcDefs.Add(FunctionDefinitionEntity.New(item.FunctionName));
                }
            }

            // Both Start and Completed log here. Completed will overwrite a Start entry.
            lock (_lock)
            {
                _instances.Add(InstanceTableEntity.New(item));
                _recents.Add(RecentPerFuncEntity.New(_containerName, item));
            }

            if (item.IsCompleted())
            {
                // For completed items, aggregate total passed and failed within a time bucket.
                // Time aggregate is flushed later.
                // Don't flush until we've moved onto the next interval.
                {
                    var newEntity = TimelineAggregateEntity.New(_containerName, item.FunctionName, item.StartTime, _uniqueId);
                    lock (_lock)
                    {
                        // If we already have an entity at this time slot (specified by rowkey), then use that so that
                        // we update the existing counters.
                        var existingEntity = _timespan.GetFromRowKey(newEntity.RowKey);
                        if (existingEntity == null)
                        {
                            _timespan.Add(newEntity);
                            existingEntity = newEntity;
                        }

                        Increment(item, existingEntity);
                    }
                }
            }

            // Flush every 100 items, maximize with tables.
            Task t1 = FlushIntancesAsync(false);
            Task t2 = FlushTimelineAggregateAsync();
            await Task.WhenAll(t1, t2);
        }
Esempio n. 9
0
        public async Task AddAsync(FunctionInstanceLogItem item, CancellationToken cancellationToken = default(CancellationToken))
        {
            item.Validate();

            {
                lock (_lock)
                {
                    StartBackgroundFlusher();
                    if (_container == null)
                    {
                        _container = new ContainerActiveLogger(_containerName, _instanceTable);
                    }
                    if (_instanceLogger == null)
                    {
                        int size = GetContainerSize();
                        _instanceLogger = new CloudTableInstanceCountLogger(_containerName, _instanceTable, size);
                    }
                }
                if (item.IsCompleted())
                {
                    _container.Decrement(item.FunctionInstanceId);
                    _instanceLogger.Decrement(item.FunctionInstanceId);
                }
                else
                {
                    _container.Increment(item.FunctionInstanceId);
                    _instanceLogger.Increment(item.FunctionInstanceId);
                }
            }

            lock (_lock)
            {
                if (_seenFunctions.Add(item.FunctionName))
                {
                    _funcDefs.Add(FunctionDefinitionEntity.New(item.FunctionName));
                }
            }

            if (!item.IsCompleted())
            {
                return;
            }

            lock (_lock)
            {
                _instances.Add(InstanceTableEntity.New(item));
                _recents.Add(RecentPerFuncEntity.New(_containerName, item));
            }

            // Time aggregate is flushed later.
            // Don't flush until we've moved onto the next interval.
            {
                var rowKey = TimelineAggregateEntity.RowKeyTimeInterval(item.FunctionName, item.StartTime, _uniqueId);

                lock (_lock)
                {
                    TimelineAggregateEntity x;
                    if (!_timespan.TryGetValue(rowKey, out x))
                    {
                        // Can we flush the old counters?
                        x = TimelineAggregateEntity.New(_containerName, item.FunctionName, item.StartTime, _uniqueId);
                        _timespan[rowKey] = x;
                    }
                    Increment(item, x);
                }
            }

            // Flush every 100 items, maximize with tables.
            Task t1 = FlushIntancesAsync(false);
            Task t2 = FlushTimelineAggregateAsync();
            await Task.WhenAll(t1, t2);
        }
Esempio n. 10
0
        public Task AddAsync(FunctionInstanceLogItem item, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.Validate();
            item.FunctionId = FunctionId.Build(this._hostName, item.FunctionName);

            // Both Start and Completed log here. Completed will overwrite a Start entry.
            lock (_lock)
            {
                _activeFuncs[item.FunctionInstanceId] = item;
            }

            lock (_lock)
            {
                StartBackgroundFlusher();
                if (_container == null)
                {
                    _container = new ContainerActiveLogger(_machineName, _logTableProvider);
                }
                if (_instanceLogger == null)
                {
                    int size = GetContainerSize();
                    _instanceLogger = new CloudTableInstanceCountLogger(_machineName, _logTableProvider, size);
                }
            }

            if (item.IsCompleted())
            {
                _container.Decrement(item.FunctionInstanceId);
                _instanceLogger.Decrement(item.FunctionInstanceId);

                lock (_lock)
                {
                    _completedFunctions.Add(item.FunctionInstanceId);
                }
            }
            else
            {
                _container.Increment(item.FunctionInstanceId);
                _instanceLogger.Increment(item.FunctionInstanceId);
            }

            lock (_lock)
            {
                if (_seenFunctions.Add(item.FunctionName))
                {
                    _funcDefs.Add(FunctionDefinitionEntity.New(item.FunctionId, item.FunctionName));
                }
            }

            if (item.IsCompleted())
            {
                // For completed items, aggregate total passed and failed within a time bucket.
                // Time aggregate is flushed later.
                // Don't flush until we've moved onto the next interval.
                {
                    var newEntity = TimelineAggregateEntity.New(_machineName, item.FunctionId, item.StartTime, _uniqueId);
                    lock (_lock)
                    {
                        // If we already have an entity at this time slot (specified by rowkey), then use that so that
                        // we update the existing counters.
                        var existingEntity = _timespan.GetFromRowKey(newEntity.RowKey);
                        if (existingEntity == null)
                        {
                            _timespan.Add(newEntity);
                            existingEntity = newEntity;
                        }

                        Increment(item, existingEntity);
                    }
                }
            }

            // Results will get written on a background thread
            return(Task.FromResult(0));
        }
Esempio n. 11
0
        public Task AddAsync(FunctionInstanceLogItem item, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.Validate();
            item.FunctionId = FunctionId.Build(this._hostName, item.FunctionName);

            // Both Start and Completed log here. Completed will overwrite a Start entry.
            lock (_lock)
            {
                // Permanent failures when flushing to storage can result in many log entries being buffered.
                // This basically becomes a memory leak. Mitigate by enforcing a max.
                if (_activeFuncs.Count >= MaxBufferedEntryCount || _completedFunctions.Count >= MaxBufferedEntryCount)
                {
                    _onException?.Invoke(new Exception($"The limit on the number of buffered log entries was reached. A total of '{MaxBufferedEntryCount}' log entries were dropped."));
                    _activeFuncs.Clear();
                    _completedFunctions.Clear();
                }

                _activeFuncs[item.FunctionInstanceId] = item;
            }

            lock (_lock)
            {
                StartBackgroundFlusher();
                if (_container == null)
                {
                    _container = new ContainerActiveLogger(_machineName, _logTableProvider);
                }
                if (_instanceLogger == null)
                {
                    int size = GetContainerSize();
                    _instanceLogger = new CloudTableInstanceCountLogger(_machineName, _logTableProvider, size);
                }
            }

            if (item.IsCompleted())
            {
                _container.Decrement(item.FunctionInstanceId);
                _instanceLogger.Decrement(item.FunctionInstanceId);

                lock (_lock)
                {
                    _completedFunctions.Add(item.FunctionInstanceId);
                }
            }
            else
            {
                _container.Increment(item.FunctionInstanceId);
                _instanceLogger.Increment(item.FunctionInstanceId);
            }

            lock (_lock)
            {
                if (_seenFunctions.Add(item.FunctionName))
                {
                    _funcDefs.Add(FunctionDefinitionEntity.New(item.FunctionId, item.FunctionName));
                }
            }

            if (item.IsCompleted())
            {
                // For completed items, aggregate total passed and failed within a time bucket.
                // Time aggregate is flushed later.
                // Don't flush until we've moved onto the next interval.
                {
                    var newEntity = TimelineAggregateEntity.New(_machineName, item.FunctionId, item.StartTime, _uniqueId);
                    lock (_lock)
                    {
                        // If we already have an entity at this time slot (specified by rowkey), then use that so that
                        // we update the existing counters.
                        var existingEntity = _timespan.GetFromRowKey(newEntity.RowKey);
                        if (existingEntity == null)
                        {
                            _timespan.Add(newEntity);
                            existingEntity = newEntity;
                        }

                        Increment(item, existingEntity);
                    }
                }
            }

            // Results will get written on a background thread
            return(Task.FromResult(0));
        }