public void JobHost_NoStorage_Succeeds()
        {
            using (EnvVarHolder.Set("AzureWebJobsStorage", null))
                using (EnvVarHolder.Set("AzureWebJobsDashboard", null))
                {
                    JobHostConfiguration config = new JobHostConfiguration()
                    {
                        TypeLocator = new FakeTypeLocator(typeof(BasicTest))
                    };
                    Assert.Null(config.InternalStorageConfiguration);

                    // Explicitly disalbe storage.
                    config.HostId = Guid.NewGuid().ToString("n");
                    config.DashboardConnectionString = null;
                    config.StorageConnectionString   = null;

                    var randomValue = Guid.NewGuid().ToString();

                    StringBuilder sbLoggingCallbacks = new StringBuilder();
                    var           fastLogger         = new FastLogger();
                    config.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger);

                    JobHost host = new JobHost(config);

                    // Manually invoked.
                    var method = typeof(BasicTest).GetMethod("Method", BindingFlags.Public | BindingFlags.Static);

                    host.Call(method, new { value = randomValue });
                    Assert.True(BasicTest.Called);

                    Assert.Equal(2, fastLogger.List.Count); // We should be batching, so flush not called yet.

                    host.Start();                           // required to call stop()
                    host.Stop();                            // will ensure flush is called.

                    // Verify fast logs
                    Assert.Equal(3, fastLogger.List.Count);

                    var startMsg = fastLogger.List[0];
                    Assert.Equal("BasicTest.Method", startMsg.FunctionName);
                    Assert.Equal(null, startMsg.EndTime);
                    Assert.NotNull(startMsg.StartTime);

                    var endMsg = fastLogger.List[1];
                    Assert.Equal(startMsg.FunctionName, endMsg.FunctionName);
                    Assert.Equal(startMsg.StartTime, endMsg.StartTime);
                    Assert.Equal(startMsg.FunctionInstanceId, endMsg.FunctionInstanceId);
                    Assert.NotNull(endMsg.EndTime); // signal completed
                    Assert.True(endMsg.StartTime <= endMsg.EndTime);
                    Assert.Null(endMsg.ErrorDetails);
                    Assert.Null(endMsg.ParentId);

                    Assert.Equal(2, endMsg.Arguments.Count);
                    Assert.True(endMsg.Arguments.ContainsKey("log"));
                    Assert.Equal(randomValue, endMsg.Arguments["value"]);
                    Assert.Equal("val=" + randomValue, endMsg.LogOutput.Trim());

                    Assert.Same(FastLogger.FlushEntry, fastLogger.List[2]);
                }
        }
        protected override void OnInitializeConfig(ScriptHostConfiguration config)
        {
            base.OnInitializeConfig(config);

            // Note: this method can be called many times for the same ScriptHostConfiguration
            // so no changes should be made to the configuration itself. It is safe to modify
            // ScriptHostConfiguration.Host config though, since the inner JobHostConfiguration
            // is created anew on each restart.

            // Add our WebHost specific services
            var hostConfig = config.HostConfig;

            hostConfig.AddService <IMetricsLogger>(_metricsLogger);

            // Add our exception handler
            hostConfig.AddService <IWebJobsExceptionHandler>(_exceptionHandler);

            // Register the new "FastLogger" for Dashboard support
            var dashboardString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Dashboard);

            if (dashboardString != null)
            {
                var fastLogger = new FastLogger(dashboardString);
                hostConfig.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger);
            }
            hostConfig.DashboardConnectionString = null; // disable slow logging
        }
Ejemplo n.º 3
0
        public async Task JobHost_NoStorage_Succeeds()
        {
            var fastLogger = new FastLogger();

            using (EnvVarHolder.Set("AzureWebJobsStorage", null))
                using (EnvVarHolder.Set("AzureWebJobsDashboard", null))
                {
                    IHost host = new HostBuilder()
                                 .ConfigureWebJobs(b =>
                    {
                        b.AddTableLogging(fastLogger);
                    })
                                 .ConfigureTypeLocator(typeof(BasicTest))
                                 .Build();

                    var randomValue = Guid.NewGuid().ToString();

                    StringBuilder sbLoggingCallbacks = new StringBuilder();

                    // Manually invoked.
                    var method = typeof(BasicTest).GetMethod("Method", BindingFlags.Public | BindingFlags.Static);

                    var lockManager = host.Services.GetRequiredService <IDistributedLockManager>();
                    Assert.IsType <InMemoryDistributedLockManager>(lockManager);

                    await host.GetJobHost().CallAsync(method, new { value = randomValue });

                    Assert.True(BasicTest.Called);

                    Assert.Equal(2, fastLogger.List.Count); // We should be batching, so flush not called yet.

                    host.Start();                           // required to call stop()
                    await host.StopAsync();                 // will ensure flush is called.

                    // Verify fast logs
                    Assert.Equal(3, fastLogger.List.Count);

                    var startMsg = fastLogger.List[0];
                    Assert.Equal("BasicTest.Method", startMsg.FunctionName);
                    Assert.Equal(null, startMsg.EndTime);
                    Assert.NotNull(startMsg.StartTime);

                    var endMsg = fastLogger.List[1];
                    Assert.Equal(startMsg.FunctionName, endMsg.FunctionName);
                    Assert.Equal(startMsg.StartTime, endMsg.StartTime);
                    Assert.Equal(startMsg.FunctionInstanceId, endMsg.FunctionInstanceId);
                    Assert.NotNull(endMsg.EndTime); // signal completed
                    Assert.True(endMsg.StartTime <= endMsg.EndTime);
                    Assert.Null(endMsg.ErrorDetails);
                    Assert.Null(endMsg.ParentId);

                    Assert.Equal(2, endMsg.Arguments.Count);
                    Assert.True(endMsg.Arguments.ContainsKey("log"));
                    Assert.Equal(randomValue, endMsg.Arguments["value"]);

                    Assert.Equal("val=" + randomValue, endMsg.LogOutput.Trim());

                    Assert.Same(FastLogger.FlushEntry, fastLogger.List[2]);
                }// EnvVarHolder
        }
Ejemplo n.º 4
0
 public static void LogStatic(string msg, Exception ex = null, Pure.Data.MessageType type = Pure.Data.MessageType.Debug)
 {
     if (ex != null)
     {
         msg += " -----> Error : " + ex;
     }
     FastLogger.WriteText(logPrifix, msg);
 }
Ejemplo n.º 5
0
 public static void LogStatic(string msg, Exception ex = null, Pure.Data.MessageType type = Pure.Data.MessageType.Debug)
 {
     ConsoleHelper.Instance.OutputMessage(msg, ex, type);
     FastLogger.WriteLog(msg);
     if (ex != null)
     {
         FastLogger.WriteLog(ex.ToString());
     }
 }
Ejemplo n.º 6
0
        public void OnException_TracesException()
        {
            var trace = new TestTraceWriter(TraceLevel.Verbose);
            var ex    = new InvalidOperationException("Boom!");

            FastLogger.OnException(ex, trace);

            TraceEvent traceEvent = trace.Traces.Single();

            Assert.StartsWith("Error writing logs to table storage: System.InvalidOperationException: Boom!", traceEvent.Message);
            Assert.Equal(TraceLevel.Error, traceEvent.Level);
            Assert.Same(ex, traceEvent.Exception);
        }
Ejemplo n.º 7
0
        protected override void OnInitializeConfig(JobHostConfiguration config)
        {
            base.OnInitializeConfig(config);

            // Add our WebHost specific services
            config.AddService <IMetricsLogger>(_metricsLogger);

            // Register the new "FastLogger" for Dashboard support
            var dashboardString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Dashboard);

            if (dashboardString != null)
            {
                var fastLogger = new FastLogger(dashboardString);
                config.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger);
            }
            config.DashboardConnectionString = null; // disable slow logging
        }
        protected override void OnInitializeConfig(ScriptHostConfiguration config)
        {
            base.OnInitializeConfig(config);

            // Note: this method can be called many times for the same ScriptHostConfiguration
            // so no changes should be made to the configuration itself. It is safe to modify
            // ScriptHostConfiguration.Host config though, since the inner JobHostConfiguration
            // is created anew on each restart.

            // Add our WebHost specific services
            var hostConfig = config.HostConfig;
            hostConfig.AddService<IMetricsLogger>(_metricsLogger);

            // Add our exception handler
            hostConfig.AddService<IWebJobsExceptionHandler>(_exceptionHandler);

            // Register the new "FastLogger" for Dashboard support
            var dashboardString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Dashboard);
            if (dashboardString != null)
            {
                // hostId may be missing in local test scenarios. 
                var hostId = config.HostConfig.HostId ?? "default";
                var fastLogger = new FastLogger(hostId, dashboardString);
                hostConfig.AddService<IAsyncCollector<FunctionInstanceLogEntry>>(fastLogger);
            }
            hostConfig.DashboardConnectionString = null; // disable slow logging
        }
Ejemplo n.º 9
0
        protected virtual void Initialize()
        {
            // read host.json and apply to JobHostConfiguration
            string hostConfigFilePath = Path.Combine(ScriptConfig.RootScriptPath, HostConfigFileName);

            // If it doesn't exist, create an empty JSON file
            if (!File.Exists(hostConfigFilePath))
            {
                File.WriteAllText(hostConfigFilePath, "{}");
            }

            if (ScriptConfig.HostConfig.IsDevelopment)
            {
                ScriptConfig.HostConfig.UseDevelopmentSettings();
            }
            else
            {
                // TEMP: Until https://github.com/Azure/azure-webjobs-sdk-script/issues/100 is addressed
                // we're using some presets that are a good middle ground
                ScriptConfig.HostConfig.Queues.MaxPollingInterval    = TimeSpan.FromSeconds(10);
                ScriptConfig.HostConfig.Singleton.ListenerLockPeriod = TimeSpan.FromSeconds(15);
            }

            string  json       = File.ReadAllText(hostConfigFilePath);
            JObject hostConfig = JObject.Parse(json);

            ApplyConfiguration(hostConfig, ScriptConfig);

            // Set up a host level TraceMonitor that will receive notificaition
            // of ALL errors that occur. This allows us to inspect/log errors.
            var traceMonitor = new TraceMonitor()
                               .Filter(p => { return(true); })
                               .Subscribe(HandleHostError);

            ScriptConfig.HostConfig.Tracing.Tracers.Add(traceMonitor);

            if (ScriptConfig.FileLoggingEnabled)
            {
                string hostLogFilePath = Path.Combine(ScriptConfig.RootLogPath, "Host");
                TraceWriter = new FileTraceWriter(hostLogFilePath, TraceLevel.Verbose);
                ScriptConfig.HostConfig.Tracing.Tracers.Add(TraceWriter);
            }
            else
            {
                TraceWriter = NullTraceWriter.Instance;
            }

            TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "Reading host configuration file '{0}'", hostConfigFilePath));

            if (ScriptConfig.TraceWriter != null)
            {
                ScriptConfig.HostConfig.Tracing.Tracers.Add(ScriptConfig.TraceWriter);
            }
            else
            {
                ScriptConfig.TraceWriter = NullTraceWriter.Instance;
            }

            if (ScriptConfig.FileWatchingEnabled)
            {
                _fileWatcher = new FileSystemWatcher(ScriptConfig.RootScriptPath)
                {
                    IncludeSubdirectories = true,
                    EnableRaisingEvents   = true
                };
                _fileWatcher.Changed += OnFileChanged;
                _fileWatcher.Created += OnFileChanged;
                _fileWatcher.Deleted += OnFileChanged;
                _fileWatcher.Renamed += OnFileChanged;
            }

            // If a file change should result in a restart, we debounce the event to
            // ensure that only a single restart is triggered within a specific time window.
            // This allows us to deal with a large set of file change events that might
            // result from a bulk copy/unzip operation. In such cases, we only want to
            // restart after ALL the operations are complete and there is a quiet period.
            _restart = (e) =>
            {
                TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "File change of type '{0}' detected for '{1}'", e.ChangeType, e.FullPath));
                TraceWriter.Verbose("Host configuration has changed. Signaling restart.");

                // signal host restart
                _restartEvent.Set();
            };
            _restart = _restart.Debounce(500);

            // take a snapshot so we can detect function additions/removals
            _directoryCountSnapshot = Directory.EnumerateDirectories(ScriptConfig.RootScriptPath).Count();

            var dashboardString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Dashboard);

            var config = ScriptConfig.HostConfig;

            if (dashboardString != null)
            {
                var fastLogger = new FastLogger(dashboardString);
                config.AddService <IAsyncCollector <FunctionInstanceLogEntry> >(fastLogger);
            }
            config.DashboardConnectionString = null; // disable slow logging

            IMetricsLogger metricsLogger = ScriptConfig.HostConfig.GetService <IMetricsLogger>();

            if (metricsLogger == null)
            {
                ScriptConfig.HostConfig.AddService <IMetricsLogger>(new MetricsLogger());
            }

            // Bindings may use name resolution, so provide this before reading the bindings.
            var nameResolver = new NameResolver();

            var storageString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);

            if (storageString == null)
            {
                // Disable core storage
                ScriptConfig.HostConfig.StorageConnectionString = null;
            }

            ScriptConfig.HostConfig.NameResolver = nameResolver;

            List <FunctionDescriptorProvider> descriptionProviders = new List <FunctionDescriptorProvider>()
            {
                new ScriptFunctionDescriptorProvider(this, ScriptConfig),
                new NodeFunctionDescriptorProvider(this, ScriptConfig),
                new CSharpFunctionDescriptionProvider(this, ScriptConfig)
            };

            // read all script functions and apply to JobHostConfiguration
            Collection <FunctionDescriptor> functions = ReadFunctions(ScriptConfig, descriptionProviders);
            string defaultNamespace = "Host";
            string typeName         = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", defaultNamespace, "Functions");

            TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "Generating {0} job function(s)", functions.Count));
            Type        type  = FunctionGenerator.Generate(HostAssemblyName, typeName, functions);
            List <Type> types = new List <Type>();

            types.Add(type);

            ScriptConfig.HostConfig.TypeLocator = new TypeLocator(types);

            ApplyBindingConfiguration(functions, ScriptConfig.HostConfig);

            Functions = functions;
        }
        protected virtual void Initialize()
        {
            // read host.json and apply to JobHostConfiguration
            string hostConfigFilePath = Path.Combine(ScriptConfig.RootScriptPath, HostConfigFileName);

            // If it doesn't exist, create an empty JSON file
            if (!File.Exists(hostConfigFilePath))
            {
                File.WriteAllText(hostConfigFilePath, "{}");
            }

            if (ScriptConfig.HostConfig.IsDevelopment)
            {
                ScriptConfig.HostConfig.UseDevelopmentSettings();
            }
            else
            {
                // TEMP: Until https://github.com/Azure/azure-webjobs-sdk-script/issues/100 is addressed
                // we're using some presets that are a good middle ground
                ScriptConfig.HostConfig.Queues.MaxPollingInterval = TimeSpan.FromSeconds(10);
                ScriptConfig.HostConfig.Singleton.ListenerLockPeriod = TimeSpan.FromSeconds(15);
            }

            string json = File.ReadAllText(hostConfigFilePath);
            JObject hostConfig = JObject.Parse(json);
            ApplyConfiguration(hostConfig, ScriptConfig);

            // Set up a host level TraceMonitor that will receive notificaition
            // of ALL errors that occur. This allows us to inspect/log errors.
            var traceMonitor = new TraceMonitor()
                .Filter(p => { return true; })
                .Subscribe(HandleHostError);
            ScriptConfig.HostConfig.Tracing.Tracers.Add(traceMonitor);

            if (ScriptConfig.FileLoggingEnabled)
            {
                string hostLogFilePath = Path.Combine(ScriptConfig.RootLogPath, "Host");
                TraceWriter = new FileTraceWriter(hostLogFilePath, TraceLevel.Verbose);
                ScriptConfig.HostConfig.Tracing.Tracers.Add(TraceWriter);
            }
            else
            {
                TraceWriter = NullTraceWriter.Instance;
            }

            TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "Reading host configuration file '{0}'", hostConfigFilePath));

            if (ScriptConfig.TraceWriter != null)
            {
                ScriptConfig.HostConfig.Tracing.Tracers.Add(ScriptConfig.TraceWriter);
            }
            else
            {
                ScriptConfig.TraceWriter = NullTraceWriter.Instance;
            }

            if (ScriptConfig.FileWatchingEnabled)
            {
                _fileWatcher = new FileSystemWatcher(ScriptConfig.RootScriptPath)
                {
                    IncludeSubdirectories = true,
                    EnableRaisingEvents = true
                };
                _fileWatcher.Changed += OnFileChanged;
                _fileWatcher.Created += OnFileChanged;
                _fileWatcher.Deleted += OnFileChanged;
                _fileWatcher.Renamed += OnFileChanged;
            }

            // If a file change should result in a restart, we debounce the event to
            // ensure that only a single restart is triggered within a specific time window.
            // This allows us to deal with a large set of file change events that might
            // result from a bulk copy/unzip operation. In such cases, we only want to
            // restart after ALL the operations are complete and there is a quiet period.
            _restart = (e) =>
            {
                TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "File change of type '{0}' detected for '{1}'", e.ChangeType, e.FullPath));
                TraceWriter.Verbose("Host configuration has changed. Signaling restart.");

                // signal host restart
                _restartEvent.Set();
            };
            _restart = _restart.Debounce(500);

            // take a snapshot so we can detect function additions/removals
            _directoryCountSnapshot = Directory.EnumerateDirectories(ScriptConfig.RootScriptPath).Count();

            var dashboardString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Dashboard);

            var config = ScriptConfig.HostConfig;
            if (dashboardString != null)
            {
                var fastLogger = new FastLogger(dashboardString);
                config.AddService<IAsyncCollector<FunctionInstanceLogEntry>>(fastLogger);
            }
            config.DashboardConnectionString = null; // disable slow logging 

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

            // Bindings may use name resolution, so provide this before reading the bindings. 
            var nameResolver = new NameResolver();

            var storageString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);
            if (storageString == null)
            {
                // Disable core storage 
                ScriptConfig.HostConfig.StorageConnectionString = null;
            }
                      
            ScriptConfig.HostConfig.NameResolver = nameResolver;

            List<FunctionDescriptorProvider> descriptionProviders = new List<FunctionDescriptorProvider>()
            {
                new ScriptFunctionDescriptorProvider(this, ScriptConfig),
                new NodeFunctionDescriptorProvider(this, ScriptConfig),
                new CSharpFunctionDescriptionProvider(this, ScriptConfig)
            };

            // read all script functions and apply to JobHostConfiguration
            Collection<FunctionDescriptor> functions = ReadFunctions(ScriptConfig, descriptionProviders);
            string defaultNamespace = "Host";
            string typeName = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", defaultNamespace, "Functions");
            TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "Generating {0} job function(s)", functions.Count));
            Type type = FunctionGenerator.Generate(HostAssemblyName, typeName, functions);
            List<Type> types = new List<Type>();
            types.Add(type);

            ScriptConfig.HostConfig.TypeLocator = new TypeLocator(types);

            ApplyBindingConfiguration(functions, ScriptConfig.HostConfig);

            Functions = functions;
        }
Ejemplo n.º 11
0
 static HostServices()
 {
     Log = new FastLogger();
 }
Ejemplo n.º 12
0
        static HostServices()
        {
            Log = new FastLogger();

            Container.RegisterInstance <ILog>(Log);
        }