Example #1
0
        // Lookup a single instance by id.
        public async Task <FunctionInstanceLogItem> LookupFunctionInstanceAsync(Guid id)
        {
            var tables = await _tableLookup.ListTablesAsync();

            Task <FunctionInstanceLogItem>[] taskLookups = Array.ConvertAll(tables, async instanceTable =>
            {
                // Create a retrieve operation that takes a customer entity.
                TableOperation retrieveOperation = InstanceTableEntity.GetRetrieveOperation(id);

                // Execute the retrieve operation.
                TableResult retrievedResult = await instanceTable.SafeExecuteAsync(retrieveOperation);

                var entity = (InstanceTableEntity)retrievedResult.Result;

                if (entity == null)
                {
                    return(null);
                }
                return(entity.ToFunctionLogItem());
            });

            FunctionInstanceLogItem[] results = await Task.WhenAll(taskLookups);

            foreach (var result in results)
            {
                if (result != null)
                {
                    return(result);
                }
            }
            return(null);
        }
Example #2
0
        // Could flush on a timer.
        private async Task FlushIntancesAsync()
        {
            // Before writing, give items a chance to refresh
            var itemsSnapshot = Update();

            // Write entries
            var instances     = Array.ConvertAll(itemsSnapshot, item => InstanceTableEntity.New(item));
            var recentInvokes = Array.ConvertAll(itemsSnapshot, item => RecentPerFuncEntity.New(_machineName, item));

            FunctionDefinitionEntity[] functionDefinitions;

            lock (_lock)
            {
                functionDefinitions = _funcDefs.ToArray();
                _funcDefs.Clear();
            }
            Task t1 = WriteBatchAsync(instances);
            Task t2 = WriteBatchAsync(recentInvokes);
            Task t3 = WriteBatchAsync(functionDefinitions);
            await Task.WhenAll(t1, t2, t3);

            // After we write to table, remove all completed functions.
            lock (_lock)
            {
                foreach (var completedId in _completedFunctions)
                {
                    _activeFuncs.Remove(completedId);
                }
                _completedFunctions.Clear();
            }
        }
Example #3
0
        // Lookup a single instance by id.
        public async Task <FunctionInstanceLogItem> LookupFunctionInstanceAsync(Guid id)
        {
            // Create a retrieve operation that takes a customer entity.
            TableOperation retrieveOperation = InstanceTableEntity.GetRetrieveOperation(id);

            // Execute the retrieve operation.
            TableResult retrievedResult = await _instanceTable.SafeExecuteAsync(retrieveOperation);

            var x = (InstanceTableEntity)retrievedResult.Result;

            if (x == null)
            {
                return(null);
            }
            return(x.ToFunctionLogItem());
        }
Example #4
0
        // Could flush on a timer.
        private async Task FlushIntancesAsync()
        {
            FunctionInstanceLogItem[] itemsSnapshot;
            Guid[] completedSnapshot;
            FunctionDefinitionEntity[] functionDefinitionSnapshot;

            // Get snapshots while under the lock.
            lock (_lock)
            {
                itemsSnapshot              = _activeFuncs.Values.ToArray();
                completedSnapshot          = _completedFunctions.ToArray();
                functionDefinitionSnapshot = _funcDefs.ToArray();
                _funcDefs.Clear();
            }

            // Before writing, give items a chance to refresh
            foreach (var item in itemsSnapshot)
            {
                item.Refresh(_flushInterval);
            }

            // Write entries
            var instances     = itemsSnapshot.Select(item => InstanceTableEntity.New(item));
            var recentInvokes = itemsSnapshot.Select(item => RecentPerFuncEntity.New(_machineName, item));


            Task t1 = WriteBatchAsync(instances);
            Task t2 = WriteBatchAsync(recentInvokes);
            Task t3 = WriteBatchAsync(functionDefinitionSnapshot);
            await Task.WhenAll(t1, t2, t3);

            // After we write to table, remove all completed functions.
            lock (_lock)
            {
                foreach (var completedId in completedSnapshot)
                {
                    _activeFuncs.Remove(completedId);
                    _completedFunctions.Remove(completedId);
                }
            }
        }
        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);
        }
Example #6
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);
        }