Beispiel #1
0
        internal void SystemLog(GrpcEvent msg)
        {
            RpcLog   systemLog = msg.Message.RpcLog;
            LogLevel logLevel  = (LogLevel)systemLog.Level;

            switch (logLevel)
            {
            case LogLevel.Warning:
                _workerChannelLogger.LogWarning(systemLog.Message);
                break;

            case LogLevel.Information:
                _workerChannelLogger.LogInformation(systemLog.Message);
                break;

            case LogLevel.Error:
            {
                if (systemLog.Exception != null)
                {
                    Workers.Rpc.RpcException exception = new Workers.Rpc.RpcException(systemLog.Message, systemLog.Exception.Message, systemLog.Exception.StackTrace);
                    _workerChannelLogger.LogError(exception, systemLog.Message);
                }
                else
                {
                    _workerChannelLogger.LogError(systemLog.Message);
                }
            }
            break;

            default:
                _workerChannelLogger.LogInformation(systemLog.Message);
                break;
            }
        }
        internal void WorkerInitResponse(GrpcEvent initEvent)
        {
            _startLatencyMetric?.Dispose();
            _startLatencyMetric = null;

            _workerChannelLogger.LogDebug("Received WorkerInitResponse. Worker process initialized");
            _initMessage = initEvent.Message.WorkerInitResponse;
            _workerChannelLogger.LogDebug($"Worker capabilities: {_initMessage.Capabilities}");
            if (_initMessage.Result.IsFailure(out Exception exc))
            {
                HandleWorkerInitError(exc);
                _workerInitTask.SetResult(false);
                return;
            }
            _state = _state | RpcWorkerChannelState.Initialized;
            _workerCapabilities.UpdateCapabilities(_initMessage.Capabilities);
            _isSharedMemoryDataTransferEnabled = IsSharedMemoryDataTransferEnabled();

            if (!_isSharedMemoryDataTransferEnabled)
            {
                // If the worker does not support using shared memory data transfer, caching must also be disabled
                ScriptHost.IsFunctionDataCacheEnabled = false;
            }

            _workerInitTask.SetResult(true);
        }
Beispiel #3
0
        public void SharedMemoryDataTransferSetting_VerifyDisabledIfEnvironmentVariableAbsent()
        {
            // Enable shared memory data transfer capability in the worker
            IDictionary <string, string> capabilities = new Dictionary <string, string>()
            {
                { RpcWorkerConstants.SharedMemoryDataTransfer, "1" }
            };

            StartStream startStream = new StartStream()
            {
                WorkerId = _workerId
            };

            StreamingMessage startStreamMessage = new StreamingMessage()
            {
                StartStream = startStream
            };

            // Send worker init request and enable the capabilities
            GrpcEvent rpcEvent = new GrpcEvent(_workerId, startStreamMessage);

            _workerChannel.SendWorkerInitRequest(rpcEvent);
            _testFunctionRpcService.PublishWorkerInitResponseEvent(capabilities);

            Assert.False(_workerChannel.IsSharedMemoryDataTransferEnabled());
        }
        // send capabilities to worker, wait for WorkerInitResponse
        internal void SendWorkerInitRequest(GrpcEvent startEvent)
        {
            _workerChannelLogger.LogDebug("Worker Process started. Received StartStream message");
            _inboundWorkerEvents.Where(msg => msg.MessageType == MsgType.WorkerInitResponse)
            .Timeout(_workerConfig.CountOptions.InitializationTimeout)
            .Take(1)
            .Subscribe(WorkerInitResponse, HandleWorkerInitError);

            WorkerInitRequest initRequest = GetWorkerInitRequest();

            // Run as Functions Host V2 compatible
            if (_environment.IsV2CompatibilityMode())
            {
                _workerChannelLogger.LogDebug("Worker and host running in V2 compatibility mode");
                initRequest.Capabilities.Add(RpcWorkerConstants.V2Compatable, "true");
            }

            if (ScriptHost.IsFunctionDataCacheEnabled)
            {
                // FunctionDataCache is available from the host side - we send this to the worker.
                // As long as the worker replies back with the SharedMemoryDataTransfer capability, the cache
                // can be used.
                initRequest.Capabilities.Add(RpcWorkerConstants.FunctionDataCache, "true");
            }

            SendStreamingMessage(new StreamingMessage
            {
                WorkerInitRequest = initRequest
            });
        }
Beispiel #5
0
        public void SendLoadRequestCollection_PublishesOutboundEvents()
        {
            StartStream startStream = new StartStream()
            {
                WorkerId = _workerId
            };
            StreamingMessage startStreamMessage = new StreamingMessage()
            {
                StartStream = startStream
            };
            GrpcEvent rpcEvent = new GrpcEvent(_workerId, startStreamMessage);

            _workerChannel.SendWorkerInitRequest(rpcEvent);
            _testFunctionRpcService.PublishWorkerInitResponseEvent(new Dictionary <string, string>()
            {
                { RpcWorkerConstants.AcceptsListOfFunctionLoadRequests, "true" }
            });
            _metricsLogger.ClearCollections();
            IEnumerable <FunctionMetadata> functionMetadata = GetTestFunctionsList("node");

            _workerChannel.SetupFunctionInvocationBuffers(functionMetadata);
            _workerChannel.SendFunctionLoadRequests(null, TimeSpan.FromMinutes(5));
            var traces           = _logger.GetLogMessages();
            var functionLoadLogs = traces.Where(m => string.Equals(m.FormattedMessage, _expectedLogMsg));

            AreExpectedMetricsGenerated();
            Assert.True(functionLoadLogs.Count() == 2);
            Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, string.Format("Sending FunctionLoadRequestCollection with number of functions:'{0}'", functionMetadata.ToList().Count))));
        }
        internal void WorkerInitResponse(GrpcEvent initEvent)
        {
            _startLatencyMetric?.Dispose();
            _startLatencyMetric = null;

            _workerChannelLogger.LogDebug("Received WorkerInitResponse. Worker process initialized");
            _initMessage = initEvent.Message.WorkerInitResponse;
            _workerChannelLogger.LogDebug($"Worker capabilities: {_initMessage.Capabilities}");
            if (_initMessage.Result.IsFailure(out Exception exc))
            {
                HandleWorkerInitError(exc);
                _workerInitTask.SetResult(false);
                return;
            }
            _state = _state | RpcWorkerChannelState.Initialized;
            _workerCapabilities.UpdateCapabilities(_initMessage.Capabilities);
            _workerInitTask.SetResult(true);
        }
        public void SendWorkerInitRequest_PublishesOutboundEvent()
        {
            StartStream startStream = new StartStream()
            {
                WorkerId = _workerId
            };
            StreamingMessage startStreamMessage = new StreamingMessage()
            {
                StartStream = startStream
            };
            GrpcEvent rpcEvent = new GrpcEvent(_workerId, startStreamMessage);

            _workerChannel.SendWorkerInitRequest(rpcEvent);
            _testFunctionRpcService.PublishWorkerInitResponseEvent();
            var traces = _logger.GetLogMessages();

            Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, _expectedLogMsg)));
        }
        public void SendWorkerInitRequest_PublishesOutboundEvent_V2Compatable()
        {
            _testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionsV2CompatibilityModeKey, "true");
            StartStream startStream = new StartStream()
            {
                WorkerId = _workerId
            };
            StreamingMessage startStreamMessage = new StreamingMessage()
            {
                StartStream = startStream
            };
            GrpcEvent rpcEvent = new GrpcEvent(_workerId, startStreamMessage);

            _workerChannel.SendWorkerInitRequest(rpcEvent);
            _testFunctionRpcService.PublishWorkerInitResponseEvent();
            var traces = _logger.GetLogMessages();

            Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, _expectedLogMsg)));
            Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, "Worker and host running in V2 compatibility mode")));
        }
Beispiel #9
0
        internal void Log(GrpcEvent msg)
        {
            var      rpcLog   = msg.Message.RpcLog;
            LogLevel logLevel = (LogLevel)rpcLog.Level;

            if (_executingInvocations.TryGetValue(rpcLog.InvocationId, out ScriptInvocationContext context))
            {
                // Restore the execution context from the original invocation. This allows AsyncLocal state to flow to loggers.
                System.Threading.ExecutionContext.Run(context.AsyncExecutionContext, (s) =>
                {
                    if (rpcLog.Exception != null)
                    {
                        var exception = new Workers.Rpc.RpcException(rpcLog.Message, rpcLog.Exception.Message, rpcLog.Exception.StackTrace);
                        context.Logger.Log(logLevel, new EventId(0, rpcLog.EventId), rpcLog.Message, exception, (state, exc) => state);
                    }
                    else
                    {
                        context.Logger.Log(logLevel, new EventId(0, rpcLog.EventId), rpcLog.Message, null, (state, exc) => state);
                    }
                }, null);
            }
        }
Beispiel #10
0
        // send capabilities to worker, wait for WorkerInitResponse
        internal void SendWorkerInitRequest(GrpcEvent startEvent)
        {
            _workerChannelLogger.LogDebug("Worker Process started. Received StartStream message");
            _inboundWorkerEvents.Where(msg => msg.MessageType == MsgType.WorkerInitResponse)
            .Timeout(workerInitTimeout)
            .Take(1)
            .Subscribe(WorkerInitResponse, HandleWorkerInitError);

            WorkerInitRequest initRequest = GetWorkerInitRequest();

            // Run as Functions Host V2 compatible
            if (_environment.IsV2CompatibilityMode())
            {
                _workerChannelLogger.LogDebug("Worker and host running in V2 compatibility mode");
                initRequest.Capabilities.Add(RpcWorkerConstants.V2Compatable, "true");
            }

            SendStreamingMessage(new StreamingMessage
            {
                WorkerInitRequest = initRequest
            });
        }
        internal void Log(GrpcEvent msg)
        {
            var      rpcLog   = msg.Message.RpcLog;
            LogLevel logLevel = (LogLevel)rpcLog.Level;

            if (_executingInvocations.TryGetValue(rpcLog.InvocationId, out ScriptInvocationContext context))
            {
                // Restore the execution context from the original invocation. This allows AsyncLocal state to flow to loggers.
                System.Threading.ExecutionContext.Run(context.AsyncExecutionContext, (s) =>
                {
                    if (rpcLog.LogCategory == RpcLogCategory.CustomMetric)
                    {
                        if (rpcLog.PropertiesMap.TryGetValue(LogConstants.NameKey, out var metricName) &&
                            rpcLog.PropertiesMap.TryGetValue(LogConstants.MetricValueKey, out var metricValue))
                        {
                            // Strip off the name/value entries in the dictionary passed to Log Message and include the rest as the property bag passed to the backing ILogger
                            var rpcLogProperties = rpcLog.PropertiesMap
                                                   .Where(i => i.Key != LogConstants.NameKey && i.Key != LogConstants.MetricValueKey)
                                                   .ToDictionary(i => i.Key, i => i.Value.ToObject());
                            context.Logger.LogMetric(metricName.String, metricValue.Double, rpcLogProperties);
                        }
                    }
                    else
                    {
                        if (rpcLog.Exception != null)
                        {
                            // TODO fix RpcException catch all https://github.com/Azure/azure-functions-dotnet-worker/issues/370
                            var exception = new Workers.Rpc.RpcException(rpcLog.Message, rpcLog.Exception.Message, rpcLog.Exception.StackTrace);
                            context.Logger.Log(logLevel, new EventId(0, rpcLog.EventId), rpcLog.Message, exception, (state, exc) => state);
                        }
                        else
                        {
                            context.Logger.Log(logLevel, new EventId(0, rpcLog.EventId), rpcLog.Message, null, (state, exc) => state);
                        }
                    }
                }, null);
            }
        }
Beispiel #12
0
        public void SharedMemoryDataTransferSetting_VerifyDisabledIfWorkerCapabilityAbsent()
        {
            // Enable shared memory data transfer in the environment
            _testEnvironment.SetEnvironmentVariable(RpcWorkerConstants.FunctionsWorkerSharedMemoryDataTransferEnabledSettingName, "1");

            StartStream startStream = new StartStream()
            {
                WorkerId = _workerId
            };

            StreamingMessage startStreamMessage = new StreamingMessage()
            {
                StartStream = startStream
            };

            // Send worker init request and enable the capabilities
            GrpcEvent rpcEvent = new GrpcEvent(_workerId, startStreamMessage);

            _workerChannel.SendWorkerInitRequest(rpcEvent);
            _testFunctionRpcService.PublishWorkerInitResponseEvent();

            Assert.False(_workerChannel.IsSharedMemoryDataTransferEnabled());
        }