Skip to content

Commit

Permalink
Adding metrics logging
Browse files Browse the repository at this point in the history
  • Loading branch information
mathewc committed Mar 11, 2016
1 parent 0cfc3f7 commit 448ade6
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/WebJobs.Script.WebHost/Diagnostics/WebHostMetricsLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using Microsoft.Azure.WebJobs.Script.Diagnostics;

namespace WebJobs.Script.WebHost.Diagnostics
{
public class WebHostMetricsLogger : IMetricsLogger
{
public void BeginEvent(MetricEvent metricEvent)
{
// TODO
FunctionStartedEvent startedEvent = metricEvent as FunctionStartedEvent;
if (startedEvent != null)
{
startedEvent.StartTime = DateTime.Now;
}
}

public void EndEvent(MetricEvent metricEvent)
{
// TODO
FunctionStartedEvent startedEvent = metricEvent as FunctionStartedEvent;
if (startedEvent != null)
{
startedEvent.EndTime = DateTime.Now;
}
}
}
}
1 change: 1 addition & 0 deletions src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\FunctionsController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Diagnostics\WebHostMetricsLogger.cs" />
<Compile Include="Filters\AuthorizationLevelAttribute.cs" />
<Compile Include="FunctionSecrets.cs" />
<Compile Include="Global.asax.cs">
Expand Down
11 changes: 11 additions & 0 deletions src/WebJobs.Script.WebHost/WebScriptHostManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Script;
using Microsoft.Azure.WebJobs.Script.Description;
using Microsoft.Azure.WebJobs.Script.Diagnostics;
using WebJobs.Script.WebHost.Diagnostics;

namespace WebJobs.Script.WebHost
{
Expand Down Expand Up @@ -74,6 +77,14 @@ public FunctionDescriptor GetHttpFunctionOrNull(Uri uri)
return function;
}

protected override void OnInitializeConfig(JobHostConfiguration config)
{
base.OnInitializeConfig(config);

// Add our WebHost specific services
config.AddService<IMetricsLogger>(new WebHostMetricsLogger());
}

protected override void OnHostStarted()
{
base.OnHostStarted();
Expand Down
14 changes: 14 additions & 0 deletions src/WebJobs.Script/Description/CSharp/CSharpFunctionInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Azure.WebJobs.Script.Binding;
using Microsoft.Azure.WebJobs.Script.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Scripting;
Expand All @@ -31,6 +32,7 @@ public class CSharpFunctionInvoker : ScriptFunctionInvokerBase
private readonly Collection<FunctionBinding> _inputBindings;
private readonly Collection<FunctionBinding> _outputBindings;
private readonly IFunctionEntryPointResolver _functionEntryPointResolver;
private readonly IMetricsLogger _metrics;

private MethodInfo _function;
private CSharpFunctionSignature _functionSignature;
Expand All @@ -53,6 +55,7 @@ internal CSharpFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadat
_inputBindings = inputBindings;
_outputBindings = outputBindings;
_triggerInputName = GetTriggerInputName(functionMetadata);
_metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();

InitializeFileWatcherIfEnabled();
_resultProcessor = CreateResultProcessor();
Expand Down Expand Up @@ -150,6 +153,9 @@ private void RestorePackages()

public override async Task Invoke(object[] parameters)
{
FunctionStartedEvent startedEvent = new FunctionStartedEvent(Metadata);
_metrics.BeginEvent(startedEvent);

try
{
TraceWriter.Verbose("Function started");
Expand All @@ -175,9 +181,17 @@ public override async Task Invoke(object[] parameters)
catch (Exception ex)
{
TraceWriter.Error(ex.Message, ex is CompilationErrorException ? null : ex);

startedEvent.Success = false;
TraceWriter.Error(ex.Message, ex);

TraceWriter.Verbose("Function completed (Failure)");
throw;
}
finally
{
_metrics.EndEvent(startedEvent);
}
}

private object[] ProcessInputParameters(object[] parameters)
Expand Down
11 changes: 11 additions & 0 deletions src/WebJobs.Script/Description/NodeFunctionInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using EdgeJs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Azure.WebJobs.Script.Binding;
using Microsoft.Azure.WebJobs.Script.Diagnostics;
using Newtonsoft.Json;

namespace Microsoft.Azure.WebJobs.Script.Description
Expand All @@ -28,6 +29,7 @@ public class NodeFunctionInvoker : ScriptFunctionInvokerBase
private readonly string _script;
private readonly DictionaryJsonConverter _dictionaryJsonConverter = new DictionaryJsonConverter();
private readonly BindingMetadata _trigger;
private readonly IMetricsLogger _metrics;

private Func<object, Task<object>> _scriptFunc;
private Func<object, Task<object>> _clearRequireCache;
Expand Down Expand Up @@ -55,6 +57,7 @@ internal NodeFunctionInvoker(ScriptHost host, BindingMetadata trigger, FunctionM
_script = string.Format(CultureInfo.InvariantCulture, _functionTemplate, scriptFilePath);
_inputBindings = inputBindings;
_outputBindings = outputBindings;
_metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();

InitializeFileWatcherIfEnabled();
}
Expand Down Expand Up @@ -93,6 +96,9 @@ public override async Task Invoke(object[] parameters)
IBinder binder = (IBinder)parameters[2];
ExecutionContext functionExecutionContext = (ExecutionContext)parameters[3];

FunctionStartedEvent startedEvent = new FunctionStartedEvent(Metadata);
_metrics.BeginEvent(startedEvent);

try
{
TraceWriter.Verbose(string.Format("Function started"));
Expand All @@ -113,10 +119,15 @@ public override async Task Invoke(object[] parameters)
}
catch (Exception ex)
{
startedEvent.Success = false;
TraceWriter.Error(ex.Message, ex);
TraceWriter.Verbose(string.Format("Function completed (Failure)"));
throw;
}
finally
{
_metrics.EndEvent(startedEvent);
}
}

private async Task ProcessInputBindingsAsync(IBinder binder, Dictionary<string, object> executionContext, Dictionary<string, string> bindingData)
Expand Down
15 changes: 14 additions & 1 deletion src/WebJobs.Script/Description/ScriptFunctionInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Azure.WebJobs.Script.Binding;
using Microsoft.Azure.WebJobs.Script.Diagnostics;

namespace Microsoft.Azure.WebJobs.Script.Description
{
Expand All @@ -23,6 +24,8 @@ public class ScriptFunctionInvoker : ScriptFunctionInvokerBase
private static string[] _supportedScriptTypes = new string[] { "ps1", "cmd", "bat", "py", "php", "sh", "fsx" };
private readonly string _scriptFilePath;
private readonly string _scriptType;
private readonly IMetricsLogger _metrics;

private readonly Collection<FunctionBinding> _inputBindings;
private readonly Collection<FunctionBinding> _outputBindings;

Expand All @@ -33,6 +36,7 @@ internal ScriptFunctionInvoker(string scriptFilePath, ScriptHost host, FunctionM
_scriptType = Path.GetExtension(_scriptFilePath).ToLower(CultureInfo.InvariantCulture).TrimStart('.');
_inputBindings = inputBindings;
_outputBindings = outputBindings;
_metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();
}

public static bool IsSupportedScriptType(string extension)
Expand Down Expand Up @@ -87,6 +91,9 @@ internal async Task ExecuteScriptAsync(string path, string arguments, object[] i
IBinder binder = (IBinder)invocationParameters[2];
ExecutionContext functionExecutionContext = (ExecutionContext)invocationParameters[3];

FunctionStartedEvent startedEvent = new FunctionStartedEvent(Metadata);
_metrics.BeginEvent(startedEvent);

// perform any required input conversions
string stdin = null;
if (input != null)
Expand Down Expand Up @@ -131,8 +138,14 @@ internal async Task ExecuteScriptAsync(string path, string arguments, object[] i
}
process.WaitForExit();

if (process.ExitCode != 0)
bool failed = process.ExitCode != 0;
startedEvent.Success = !failed;
_metrics.EndEvent(startedEvent);

if (failed)
{
startedEvent.Success = false;

string error = process.StandardError.ReadToEnd();
TraceWriter.Error(error);
TraceWriter.Verbose(string.Format("Function completed (Failure)"));
Expand Down
20 changes: 20 additions & 0 deletions src/WebJobs.Script/Diagnostics/FunctionStartedEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Azure.WebJobs.Script.Description;

namespace Microsoft.Azure.WebJobs.Script.Diagnostics
{
public class FunctionStartedEvent : MetricEvent
{
public FunctionStartedEvent(FunctionMetadata functionMetadata)
{
FunctionMetadata = functionMetadata;
Success = true;
}

public FunctionMetadata FunctionMetadata { get; private set; }

public bool Success { get; set; }
}
}
24 changes: 24 additions & 0 deletions src/WebJobs.Script/Diagnostics/IMetricsLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace Microsoft.Azure.WebJobs.Script.Diagnostics
{
/// <summary>
/// Defines an interface for emitting metric events from the
/// script runtime for later aggregation and reporting.
/// </summary>
public interface IMetricsLogger
{
/// <summary>
/// Begins an event.
/// </summary>
/// <param name="metricEvent">The event.</param>
void BeginEvent(MetricEvent metricEvent);

/// <summary>
/// Completes a previously started event.
/// </summary>
/// <param name="metricEvent">A previously started event.</param>
void EndEvent(MetricEvent metricEvent);
}
}
14 changes: 14 additions & 0 deletions src/WebJobs.Script/Diagnostics/MetricEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;

namespace Microsoft.Azure.WebJobs.Script.Diagnostics
{
public abstract class MetricEvent
{
public DateTime StartTime { get; set; }

public DateTime EndTime { get; set; }
}
}
19 changes: 19 additions & 0 deletions src/WebJobs.Script/Diagnostics/MetricsLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

namespace Microsoft.Azure.WebJobs.Script.Diagnostics
{
/// <summary>
/// Default implementation of <see cref="IMetricsLogger"/> that doesn't do any logging.
/// </summary>
public class MetricsLogger : IMetricsLogger
{
public void BeginEvent(MetricEvent metricEvent)
{
}

public void EndEvent(MetricEvent metricEvent)
{
}
}
}
7 changes: 7 additions & 0 deletions src/WebJobs.Script/Host/ScriptHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Azure.WebJobs.Script.Config;
using Microsoft.Azure.WebJobs.Script.Description;
using Microsoft.Azure.WebJobs.Script.Diagnostics;
using Microsoft.Azure.WebJobs.ServiceBus;
using Newtonsoft.Json.Linq;

Expand Down Expand Up @@ -119,6 +120,12 @@ public AutoResetEvent RestartEvent

protected virtual void Initialize()
{
IMetricsLogger metricsLogger = ScriptConfig.HostConfig.GetService<IMetricsLogger>();
if (metricsLogger == null)
{
ScriptConfig.HostConfig.AddService<IMetricsLogger>(new MetricsLogger());
}

List<FunctionDescriptorProvider> descriptionProviders = new List<FunctionDescriptorProvider>()
{
new ScriptFunctionDescriptorProvider(this, ScriptConfig),
Expand Down
5 changes: 5 additions & 0 deletions src/WebJobs.Script/Host/ScriptHostManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public ScriptHost Instance
{
HostId = _config.HostConfig.HostId
};
OnInitializeConfig(_config.HostConfig);
newInstance = _scriptHostFactory.Create(_config);
_traceWriter = newInstance.TraceWriter;

Expand Down Expand Up @@ -218,6 +219,10 @@ private ScriptHost[] GetLiveInstancesAndClear()
return instances;
}

protected virtual void OnInitializeConfig(JobHostConfiguration config)
{
}

protected virtual void OnHostStarted()
{
}
Expand Down
4 changes: 4 additions & 0 deletions src/WebJobs.Script/WebJobs.Script.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@
<Compile Include="Description\ServiceBusBindingMetadata.cs" />
<Compile Include="Description\TableBindingMetadata.cs" />
<Compile Include="Description\TimerBindingMetadata.cs" />
<Compile Include="Diagnostics\FunctionStartedEvent.cs" />
<Compile Include="Diagnostics\IMetricsLogger.cs" />
<Compile Include="Diagnostics\MetricEvent.cs" />
<Compile Include="Diagnostics\MetricsLogger.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Extensions\INameResolverExtensions.cs" />
<Compile Include="Host\ScriptHost.cs" />
Expand Down

0 comments on commit 448ade6

Please sign in to comment.