Example #1
0
        public void LogFunctionStarted(FunctionInstanceSnapshot snapshot)
        {
            // Which operation to run depends on whether or not the entity currently exists in the "queued" status.
            IConcurrentDocument <FunctionInstanceSnapshot> existingSnapshot = _store.Read(GetId(snapshot));

            bool previouslyQueued;

            // If the existing entity doesn't contain a StartTime, it must be in the "queued" status.
            if (existingSnapshot != null && existingSnapshot.Document != null && !existingSnapshot.Document.StartTime.HasValue)
            {
                previouslyQueued = true;
            }
            else
            {
                previouslyQueued = false;
            }

            if (!previouslyQueued)
            {
                LogFunctionStartedWhenNotPreviouslyQueued(snapshot);
            }
            else
            {
                LogFunctionStartedWhenPreviouslyQueued(snapshot, existingSnapshot.ETag);
            }
        }
Example #2
0
        public static Dictionary <string, string> CreateMetadata(FunctionInstanceSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException("snapshot");
            }

            var metadata = new Dictionary <string, string>();

            AddMetadataGuid(metadata, IdKey, snapshot.Id);
            AddMetadataString(metadata, DisplayTitleKey, snapshot.DisplayTitle);
            AddMetadataNullableDateTimeOffset(metadata, StartTimeKey, snapshot.StartTime);
            AddMetadataNullableDateTimeOffset(metadata, EndTimeKey, snapshot.EndTime);
            AddMetadataNullableBoolean(metadata, SucceededKey, snapshot.Succeeded);

            HeartbeatDescriptor heartbeat = snapshot.Heartbeat;

            if (heartbeat != null)
            {
                AddMetadataString(metadata, HeartbeatSharedContainerNameKey, heartbeat.SharedContainerName);
                AddMetadataString(metadata, HeartbeatSharedDirectoryNameKey, heartbeat.SharedDirectoryName);
                AddMetadataString(metadata, HeartbeatInstanceBlobNameKey, heartbeat.InstanceBlobName);
                AddMetadataInt32(metadata, HeartbeatExpirationInSecondsKey, heartbeat.ExpirationInSeconds);
            }

            return(metadata);
        }
        public void LogFunctionStarted(FunctionInstanceSnapshot snapshot)
        {
            // Which operation to run depends on whether or not the entity currently exists in the "queued" status.
            IConcurrentDocument<FunctionInstanceSnapshot> existingSnapshot = _store.Read(GetId(snapshot));

            bool previouslyQueued;

            // If the existing entity doesn't contain a StartTime, it must be in the "queued" status.
            if (existingSnapshot != null && existingSnapshot.Document != null && !existingSnapshot.Document.StartTime.HasValue)
            {
                previouslyQueued = true;
            }
            else
            {
                previouslyQueued = false;
            }

            if (!previouslyQueued)
            {
                LogFunctionStartedWhenNotPreviouslyQueued(snapshot);
            }
            else
            {
                LogFunctionStartedWhenPreviouslyQueued(snapshot, existingSnapshot.ETag);
            }
        }
 public void LogFunctionQueued(FunctionInstanceSnapshot snapshot)
 {
     // Ignore the return result. Only the dashboard calls this method, and it does so before enqueuing the
     // message to the host to run the function. So realistically the blob can't already exist. And even if the
     // host did see the message before this call, an existing blob just means something more recent than
     // "queued" status, so there's nothing to do here in that case anyway.
     _store.TryCreate(GetId(snapshot), snapshot);
 }
Example #5
0
 public void LogFunctionQueued(FunctionInstanceSnapshot snapshot)
 {
     // Ignore the return result. Only the dashboard calls this method, and it does so before enqueuing the
     // message to the host to run the function. So realistically the blob can't already exist. And even if the
     // host did see the message before this call, an existing blob just means something more recent than
     // "queued" status, so there's nothing to do here in that case anyway.
     _store.TryCreate(GetId(snapshot), snapshot);
 }
Example #6
0
 private void LogFunctionStartedWhenNotPreviouslyQueued(FunctionInstanceSnapshot snapshot)
 {
     // LogFunctionStarted and LogFunctionCompleted may run concurrently. Ensure LogFunctionStarted loses by just
     // doing a simple Insert that will fail if the entity already exists. LogFunctionCompleted wins by having it
     // replace the LogFunctionStarted record, if any.
     // Ignore the return value: if the item already exists, LogFunctionCompleted already ran, so there's no work
     // to do here.
     _store.TryCreate(GetId(snapshot), snapshot);
 }
 private void LogFunctionStartedWhenNotPreviouslyQueued(FunctionInstanceSnapshot snapshot)
 {
     // LogFunctionStarted and LogFunctionCompleted may run concurrently. Ensure LogFunctionStarted loses by just
     // doing a simple Insert that will fail if the entity already exists. LogFunctionCompleted wins by having it
     // replace the LogFunctionStarted record, if any.
     // Ignore the return value: if the item already exists, LogFunctionCompleted already ran, so there's no work
     // to do here.
     _store.TryCreate(GetId(snapshot), snapshot);
 }
        public void CreateOrUpdate(FunctionInstanceSnapshot snapshot, DateTimeOffset timestamp)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException("snapshot");
            }

            string innerId = CreateInnerId(timestamp, snapshot.Id);
            _store.CreateOrUpdate(innerId, RecentInvocationEntry.CreateMetadata(snapshot), String.Empty);
        }
 private void LogFunctionStartedWhenPreviouslyQueued(FunctionInstanceSnapshot snapshot, string etag)
 {
     // LogFunctionStarted and LogFunctionCompleted may run concurrently. LogFunctionQueued does not run
     // concurrently. Ensure LogFunctionStarted wins over LogFunctionQueued but loses to LogFunctionCompleted by
     // doing a Replace with ETag check that will fail if the entity has been changed.
     // LogFunctionCompleted wins by doing a Replace without an ETag check, so it will replace the
     // LogFunctionStarted (or Queued) record, if any.
     // Ignore the return value: if the ETag doesn't match, LogFunctionCompleted already ran, so there's no work
     // to do here.
     _store.TryUpdate(GetId(snapshot), etag, snapshot);
 }
Example #10
0
 private void LogFunctionStartedWhenPreviouslyQueued(FunctionInstanceSnapshot snapshot, string etag)
 {
     // LogFunctionStarted and LogFunctionCompleted may run concurrently. LogFunctionQueued does not run
     // concurrently. Ensure LogFunctionStarted wins over LogFunctionQueued but loses to LogFunctionCompleted by
     // doing a Replace with ETag check that will fail if the entity has been changed.
     // LogFunctionCompleted wins by doing a Replace without an ETag check, so it will replace the
     // LogFunctionStarted (or Queued) record, if any.
     // Ignore the return value: if the ETag doesn't match, LogFunctionCompleted already ran, so there's no work
     // to do here.
     _store.TryUpdate(GetId(snapshot), etag, snapshot);
 }
        public void CreateOrUpdate(FunctionInstanceSnapshot snapshot, DateTimeOffset timestamp)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException("snapshot");
            }

            string innerId = CreateInnerId(timestamp, snapshot.Id);

            _store.CreateOrUpdate(innerId, RecentInvocationEntry.CreateMetadata(snapshot), String.Empty);
        }
 internal InvocationLogViewModel(FunctionInstanceSnapshot snapshot, bool? heartbeatIsValid)
 {
     Id = snapshot.Id;
     FunctionName = snapshot.FunctionShortName;
     FunctionId = snapshot.FunctionId;
     FunctionFullName = snapshot.FunctionFullName;
     FunctionDisplayTitle = snapshot.DisplayTitle;
     HostInstanceId = snapshot.HostInstanceId;
     InstanceQueueName = snapshot.InstanceQueueName;
     if (snapshot.WebSiteName != null
         && snapshot.WebSiteName == Environment.GetEnvironmentVariable(WebSitesKnownKeyNames.WebSiteNameKey))
     {
         ExecutingJobRunId = new WebJobRunIdentifierViewModel((WebJobType)Enum.Parse(typeof(WebJobType),
             snapshot.WebJobType), snapshot.WebJobName, snapshot.WebJobRunId);
     }
     if (heartbeatIsValid.HasValue)
     {
         Status = snapshot.GetStatusWithHeartbeat(heartbeatIsValid.Value);
     }
     else
     {
         Status = snapshot.GetStatusWithoutHeartbeat();
     }
     switch (Status)
     {
         case FunctionInstanceStatus.Running:
             WhenUtc = snapshot.StartTime.Value.UtcDateTime;
             Duration = DateTimeOffset.UtcNow - snapshot.StartTime;
             break;
         case FunctionInstanceStatus.CompletedSuccess:
             WhenUtc = snapshot.EndTime.Value.UtcDateTime;
             Duration = snapshot.GetFinalDuration();
             break;
         case FunctionInstanceStatus.CompletedFailed:
             WhenUtc = snapshot.EndTime.Value.UtcDateTime;
             Duration = snapshot.GetFinalDuration();
             ExceptionType = snapshot.ExceptionType;
             ExceptionMessage = snapshot.ExceptionMessage;
             break;
         case FunctionInstanceStatus.NeverFinished:
             WhenUtc = snapshot.StartTime.Value.UtcDateTime;
             Duration = null;
             break;
     }
 }
 internal TriggerReasonViewModel(FunctionInstanceSnapshot underlyingObject)
 {
     UnderlyingObject = underlyingObject;
 }
        private static ParameterModel[] CreateParameterModels(CloudStorageAccount account, FunctionInstanceSnapshot snapshot)
        {
            List<ParameterModel> models = new List<ParameterModel>();

            IDictionary<string, FunctionInstanceArgument> parameters = snapshot.Arguments;
            IDictionary<string, ParameterLog> parameterLogs = LogAnalysis.GetParameterLogs(account, snapshot);

            foreach (KeyValuePair<string, FunctionInstanceArgument> parameter in parameters)
            {
                string name = parameter.Key;
                FunctionInstanceArgument argument = parameter.Value;
                ParameterLog log;

                if (parameterLogs != null && parameterLogs.ContainsKey(name))
                {
                    log = parameterLogs[name];
                }
                else
                {
                    log = null;
                }

                LogAnalysis.AddParameterModels(name, argument, log, snapshot, models);
            }

            return models.ToArray();
        }
Example #15
0
        internal static BlobBoundParameterModel CreateExtendedBlobModel(FunctionInstanceSnapshot snapshot, FunctionInstanceArgument argument)
        {
            Debug.Assert(argument != null);

            if (argument.Value == null)
            {
                return null;
            }

            string[] components = argument.Value.Split(new char[] { '/' });

            if (components.Length != 2)
            {
                return null;
            }

            var blobParam = new BlobBoundParameterModel();
            blobParam.IsOutput = argument.IsBlobOutput;
            blobParam.ConnectionStringKey = ConnectionStringProvider.GetPrefixedConnectionStringName(argument.AccountName);

            CloudStorageAccount account = argument.GetStorageAccount();
            if (account == null)
            {
                blobParam.IsConnectionStringMissing = true;
                return blobParam;
            }

            CloudBlockBlob blob = account
                .CreateCloudBlobClient()
                .GetContainerReference(components[0])
                .GetBlockBlobReference(components[1]);

            Guid? blobWriter = GetBlobWriter(blob);

            if (!blobWriter.HasValue)
            {
                blobParam.IsBlobMissing = true;
            }
            else
            {
                blobParam.OwnerId = blobWriter.Value;
                if (blobWriter.Value == snapshot.Id)
                {
                    blobParam.IsBlobOwnedByCurrentFunctionInstance = true;
                }
            }

            return blobParam;
        }
        private static ParameterModel[] CreateParameterModels(CloudStorageAccount account, FunctionInstanceSnapshot snapshot)
        {
            List<ParameterModel> models = new List<ParameterModel>();

            // It's important that we order any virtual parameters (e.g. Singleton parameters) to the end
            // so they don't interfere with actual function parameter ordering
            var parameters = snapshot.Arguments.OrderBy(p => p.Value.IsVirtualParameter);
            IDictionary<string, ParameterLog> parameterLogs = LogAnalysis.GetParameterLogs(account, snapshot);

            foreach (KeyValuePair<string, FunctionInstanceArgument> parameter in parameters)
            {
                string name = parameter.Key;
                FunctionInstanceArgument argument = parameter.Value;
                ParameterLog log;

                if (parameterLogs != null && parameterLogs.ContainsKey(name))
                {
                    log = parameterLogs[name];
                }
                else
                {
                    log = null;
                }

                LogAnalysis.AddParameterModels(name, argument, log, snapshot, models);
            }

            return models.ToArray();
        }
        public void CreateOrUpdate(FunctionInstanceSnapshot snapshot, DateTimeOffset timestamp)
        {
            string innerId = CreateInnerId(snapshot.ParentId.Value, timestamp, snapshot.Id);

            _store.CreateOrUpdate(innerId, RecentInvocationEntry.CreateMetadata(snapshot), String.Empty);
        }
        private static bool TryResolveParameters(FunctionSnapshot function, FunctionInstanceSnapshot snapshot, out IEnumerable<FunctionParameterViewModel> resolvedParameters)
        {
            List<FunctionParameterViewModel> parameters = new List<FunctionParameterViewModel>();

            foreach (KeyValuePair<string, ParameterSnapshot> parameter in function.Parameters)
            {
                if (!snapshot.Arguments.ContainsKey(parameter.Key))
                {
                    resolvedParameters = null;
                    return false;
                }
                
                FunctionParameterViewModel parameterModel = new FunctionParameterViewModel
                {
                    Name = parameter.Key,
                    Description = parameter.Value.Prompt,
                    Value = snapshot.Arguments[parameter.Key].Value
                };
                
                parameters.Add(parameterModel);
            }

            resolvedParameters = parameters;
            return true;
        }
        private FunctionSnapshot GetFunctionFromInstance(string id, out Guid parsed, out FunctionInstanceSnapshot snapshot)
        {
            if (!Guid.TryParse(id, out parsed))
            {
                snapshot = null;
                return null;
            }

            snapshot = _functionInstanceLookup.Lookup(parsed);

            if (snapshot == null)
            {
                return null;
            }

            return GetFunction(snapshot.FunctionId);
        }
        private bool? HostInstanceHasHeartbeat(FunctionInstanceSnapshot snapshot)
        {
            HeartbeatDescriptor heartbeat = snapshot.Heartbeat;

            if (heartbeat == null)
            {
                return null;
            }

            return HostInstanceHasHeartbeat(heartbeat.SharedContainerName, heartbeat.SharedDirectoryName,
                heartbeat.InstanceBlobName, heartbeat.ExpirationInSeconds);
        }
 public void LogFunctionCompleted(FunctionInstanceSnapshot snapshot)
 {
     // LogFunctionStarted and LogFunctionCompleted may run concurrently. Ensure LogFunctionCompleted wins by
     // having it replace the LogFunctionStarted record, if any.
     _store.CreateOrUpdate(GetId(snapshot), snapshot);
 }
 private static string GetId(FunctionInstanceSnapshot snapshot)
 {
     return snapshot.Id.ToString("N");
 }
Example #23
0
 private static string GetId(FunctionInstanceSnapshot snapshot)
 {
     return(snapshot.Id.ToString("N"));
 }
Example #24
0
        public void CreateOrUpdate(FunctionInstanceSnapshot snapshot, WebJobRunIdentifier webJobRunId, DateTimeOffset timestamp)
        {
            string innerId = CreateInnerId(webJobRunId, timestamp, snapshot.Id);

            _store.CreateOrUpdate(innerId, RecentInvocationEntry.CreateMetadata(snapshot), String.Empty);
        }
        private InvocationLogViewModel CreateInvocationEntry(RecentInvocationEntry entry)
        {
            Debug.Assert(entry != null);

            var metadataSnapshot = new FunctionInstanceSnapshot();
            metadataSnapshot.Id = entry.Id;
            metadataSnapshot.DisplayTitle = entry.DisplayTitle;
            metadataSnapshot.StartTime = entry.StartTime;
            metadataSnapshot.EndTime = entry.EndTime;
            metadataSnapshot.Succeeded = entry.Succeeded;
            metadataSnapshot.Heartbeat = entry.Heartbeat;
            return new InvocationLogViewModel(metadataSnapshot, HostInstanceHasHeartbeat(metadataSnapshot));
        }
        public void FunctionInstanceSnapshot_BuildDisplayTitle_CompletelyRemovesLineBreaks(string argumentValue, string expectedDisplayTitle)
        {
            FunctionInstanceSnapshot message = new FunctionInstanceSnapshot
            {
                Arguments = new Dictionary<string, FunctionInstanceArgument> 
                {
                    { "message", new FunctionInstanceArgument() { Value = argumentValue } }
                },
            };

            string displayTitle = message.DisplayTitle;

            Assert.Equal(expectedDisplayTitle, displayTitle);
            Assert.DoesNotContain("\r", displayTitle);
            Assert.DoesNotContain("\n", displayTitle);        
        }
Example #27
0
        // Get Live information from current watcher values. 
        internal static IDictionary<string, ParameterLog> GetParameterLogs(CloudStorageAccount account, FunctionInstanceSnapshot snapshot)
        {
            if (snapshot.ParameterLogs != null)
            {
                return snapshot.ParameterLogs;
            }

            if (snapshot.ParameterLogBlob == null)
            {
                return null;
            }

            CloudBlockBlob blob = snapshot.ParameterLogBlob.GetBlockBlob(account);

            string contents;

            try
            {
                contents = blob.DownloadText();
            }
            catch (StorageException exception)
            {
                // common case, no status information written.
                if (exception.IsNotFound())
                {
                    return null;
                }
                else
                {
                    throw;
                }
            }

            try
            {
                return JsonConvert.DeserializeObject<IDictionary<string, ParameterLog>>(contents,
                    JsonSerialization.Settings);
            }
            catch
            {
                // Not fatal. 
                // This could happen if the app wrote a corrupted log. 
                return null;
            }
        }
Example #28
0
 public void LogFunctionCompleted(FunctionInstanceSnapshot snapshot)
 {
     // LogFunctionStarted and LogFunctionCompleted may run concurrently. Ensure LogFunctionCompleted wins by
     // having it replace the LogFunctionStarted record, if any.
     _store.CreateOrUpdate(GetId(snapshot), snapshot);
 }
Example #29
0
        public static void AddParameterModels(string parameterName, FunctionInstanceArgument argument, ParameterLog log,
            FunctionInstanceSnapshot snapshot, ICollection<ParameterModel> parameterModels)
        {
            if (argument == null)
            {
                throw new ArgumentNullException("argument");
            }
            if (parameterModels == null)
            {
                throw new ArgumentNullException("parameterModels");
            }

            ParameterModel model = new ParameterModel
            {
                Name = parameterName,
                ArgInvokeString = argument.Value
            };

            if (log != null)
            {
                model.Status = Format(log);
            }

            if (argument.IsBlob)
            {
                model.ExtendedBlobModel = LogAnalysis.CreateExtendedBlobModel(snapshot, argument);
            }

            parameterModels.Add(model);

            // Special-case IBinder, which adds sub-parameters.
            BinderParameterLog binderLog = log as BinderParameterLog;

            if (binderLog != null)
            {
                IEnumerable<BinderParameterLogItem> items = binderLog.Items;

                if (items != null)
                {
                    int count = items.Count();
                    model.Status = String.Format(CultureInfo.CurrentCulture, "Bound {0} object{1}.", count, count != 1 ? "s" : String.Empty);

                    foreach (BinderParameterLogItem item in items)
                    {
                        if (item == null)
                        {
                            continue;
                        }

                        ParameterSnapshot itemSnapshot = HostIndexer.CreateParameterSnapshot(item.Descriptor);
                        string itemName = parameterName;
                        if (!string.IsNullOrEmpty(itemSnapshot.AttributeText))
                        {
                            itemName += ": " + itemSnapshot.AttributeText;
                        }
                        FunctionInstanceArgument itemArgument = FunctionIndexer.CreateFunctionInstanceArgument(item.Value, item.Descriptor);

                        AddParameterModels(itemName, itemArgument, item.Log, snapshot, parameterModels);
                    }
                }
            }
        }
        private void CreateOrUpdateIndexEntries(FunctionInstanceSnapshot snapshot, DateTimeOffset timestamp, WebJobRunIdentifier webJobRunId)
        {
            _recentInvocationsWriter.CreateOrUpdate(snapshot, timestamp);
            _recentInvocationsByFunctionWriter.CreateOrUpdate(snapshot, timestamp);

            if (webJobRunId != null)
            {
                _recentInvocationsByJobRunWriter.CreateOrUpdate(snapshot, webJobRunId, timestamp);
            }

            if (snapshot.ParentId.HasValue)
            {
                _recentInvocationsByParentWriter.CreateOrUpdate(snapshot, timestamp);
            }
        }
        public static Dictionary<string, string> CreateMetadata(FunctionInstanceSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException("snapshot");
            }

            var metadata = new Dictionary<string, string>();

            AddMetadataGuid(metadata, IdKey, snapshot.Id);
            AddMetadataString(metadata, DisplayTitleKey, snapshot.DisplayTitle);
            AddMetadataNullableDateTimeOffset(metadata, StartTimeKey, snapshot.StartTime);
            AddMetadataNullableDateTimeOffset(metadata, EndTimeKey, snapshot.EndTime);
            AddMetadataNullableBoolean(metadata, SucceededKey, snapshot.Succeeded);

            HeartbeatDescriptor heartbeat = snapshot.Heartbeat;

            if (heartbeat != null)
            {
                AddMetadataString(metadata, HeartbeatSharedContainerNameKey, heartbeat.SharedContainerName);
                AddMetadataString(metadata, HeartbeatSharedDirectoryNameKey, heartbeat.SharedDirectoryName);
                AddMetadataString(metadata, HeartbeatInstanceBlobNameKey, heartbeat.InstanceBlobName);
                AddMetadataInt32(metadata, HeartbeatExpirationInSecondsKey, heartbeat.ExpirationInSeconds);
            }

            return metadata;
        }