Exemplo n.º 1
0
 private void ReportServiceHealth(
     ServiceFabricDiscoveryOptions options,
     Uri serviceName,
     HealthState state,
     string description = null)
 {
     // TODO: this method and the one below have repeated code. Refactor out.
     var healthReport = new ServiceHealthReport(
         serviceName: serviceName,
         healthInformation: new HealthInformation(
             sourceId: HealthReportSourceId,
             property: HealthReportProperty,
             healthState: state)
         {
             Description = description,
             TimeToLive = HealthReportTimeToLive(options),
             RemoveWhenExpired = true,
         });
     var sendOptions = new HealthReportSendOptions
     {
         // Report immediately if unhealthy or if explicitly requested
         Immediate = options.AlwaysSendImmediateHealthReports ? true : state != HealthState.Ok
     };
     try
     {
         _serviceFabricCaller.ReportHealth(healthReport, sendOptions);
     }
     catch (Exception ex) // TODO: davidni: not fatal?
     {
         Log.ServiceHealthReportFailed(_logger, state, serviceName, ex);
     }
 }
Exemplo n.º 2
0
        /// <summary>
        /// Reports health at the IS service level.
        /// </summary>
        private void UpdateCoordinatorHealthStatus(HealthState serviceHealthState, string description)
        {
            traceType.WriteInfo("Reporting coordinator status: {0}: {1}", serviceHealthState, description);

            var hi = new HealthInformation(
                InfrastructureService.Constants.HealthReportSourceId,
                InfrastructureService.Constants.CoordinatorStatus,
                serviceHealthState)
            {
                Description = description,
            };

            TimeSpan ttl = this.configReader.CoordinatorStatusHealthEventTTL;

            if (ttl > TimeSpan.Zero)
            {
                hi.TimeToLive        = ttl;
                hi.RemoveWhenExpired = false;
            }

            var serviceUri   = new Uri(this.environment.ServiceName);
            var healthReport = new ServiceHealthReport(serviceUri, hi);

            this.healthClient.ReportHealth(healthReport);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Reports health at the IS service level.
        /// </summary>
        private void UpdateCoordinatorHealthStatus(HealthState serviceHealthState, string description, TimeSpan runInterval)
        {
            // Until v5.6, RDBug#8034630 results in descriptions over 4KB causing an exception.
            // For now, trim the string well below that limit, to avoid the exception.
            const int DescriptionMaxLength = 3 * 1024;

            if (description.Length > DescriptionMaxLength)
            {
                description = description.Substring(0, DescriptionMaxLength) + "[Truncated]";
            }

            var hi = new HealthInformation(
                InfrastructureService.Constants.HealthReportSourceId,
                InfrastructureService.Constants.CoordinatorStatus,
                serviceHealthState)
            {
                Description       = description,
                RemoveWhenExpired = true,
                TimeToLive        = TimeSpan.FromSeconds(runInterval.TotalSeconds * 10),
            };

            var serviceUri   = new Uri(this.environment.ServiceName);
            var healthReport = new ServiceHealthReport(serviceUri, hi);

            this.healthClient.ReportHealth(healthReport);
        }
        /// <summary>
        /// Converts a <see cref="HealthReport"/> to a <see cref="ServiceHealthReport"/>.
        /// </summary>
        /// <param name="healthReport">The health report.</param>
        /// <returns>Returns the converted <see cref="ServiceHealthReport"/>.</returns>
        public static ServiceHealthReport ToServiceHealthReport(this HealthReport healthReport)
        {
            ServiceHealthReport serviceHealth = new ServiceHealthReport();

            foreach (var(name, entry) in healthReport.Entries)
            {
                HealthCheck healthCheck = new HealthCheck
                {
                    Name        = name,
                    Description = entry.Description,
                    Status      = entry.Status.ToString(),
                    Duration    = new Duration()
                    {
                        Milliseconds = entry.Duration.Milliseconds,
                        Seconds      = entry.Duration.Seconds,
                        Ticks        = entry.Duration.Ticks
                    }
                };
                serviceHealth.HealthChecks.Add(healthCheck);
            }
            serviceHealth.Status        = healthReport.Status.ToString();
            serviceHealth.TotalDuration = new Duration()
            {
                Ticks        = healthReport.TotalDuration.Ticks,
                Seconds      = healthReport.TotalDuration.Seconds,
                Milliseconds = healthReport.TotalDuration.Milliseconds
            };
            return(serviceHealth);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Maps the controller and health check end points.
        /// </summary>
        /// <param name="app">The application builder. </param>
        /// <param name="serviceName">The service name. </param>
        /// <returns>Returns <see cref="IApplicationBuilder"/> to chain further upon.</returns>
        public static IApplicationBuilder MapControllerAndHealthCheckEndPoints(this IApplicationBuilder app, string serviceName)
        {
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapHealthChecks($"{serviceName}/health", new HealthCheckOptions()
                {
                    ResponseWriter = async(context, result) =>
                    {
                        IMessageSerializer messageSerializer = app.ApplicationServices.GetService <IMessageSerializer>();
                        IMapper mapper = app.ApplicationServices.GetService <IMapper>();
                        Guid requestId = Guid.Empty;
                        ServiceHealthCheckResponse response;
                        if (context.Request.Headers.ContainsKey("Request-Id") && Guid.TryParse(context.Request.Headers["Request-Id"].FirstOrDefault(), out requestId))
                        {
                            ServiceHealthReport report = result.ToServiceHealthReport();
                            response = new ServiceHealthCheckResponse(requestId, mapper.Map <ServiceHealthReportDto>(report), "", true);
                        }
                        else
                        {
                            response = new ServiceHealthCheckResponse(requestId, null, "Please provide a 'Request-Id' header with request id as valid guid.", false);
                        }

                        string json = messageSerializer.SerializeToString(response);
                        context.Response.ContentType = $"application/{messageSerializer.SerializerType}";
                        await context.Response.WriteAsync(json);
                    }
                });
            });
            return(app);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Posts a health report against Patch Orchestration Application's NodeAgentService
        /// </summary>
        /// <param name="fabricClient">Fabric client object to carry out HM operations</param>
        /// <param name="applicationName">Name of the application to construct servicename</param>
        /// <param name="healthReportProperty">Property of the health report</param>
        /// <param name="description">Description of the health report</param>
        /// <param name="healthState">HealthState for the health report</param>
        /// <param name="timeToLiveInMinutes">Time to live in minutes for health report</param>
        internal static NodeAgentSfUtilityExitCodes PostServiceHealthReport(FabricClient fabricClient, Uri applicationName, string healthReportProperty, string description,
                                                                            HealthState healthState, long timeToLiveInMinutes = -1)
        {
            HealthInformation healthInformation = new HealthInformation(SourceId, healthReportProperty,
                                                                        healthState)
            {
                RemoveWhenExpired = true,
                Description       = description
            };

            if (timeToLiveInMinutes >= 0)
            {
                healthInformation.TimeToLive = TimeSpan.FromMinutes(timeToLiveInMinutes);
            }

            try
            {
                ServiceHealthReport healthReport = new ServiceHealthReport(new Uri(applicationName + ServiceNameSuffix), healthInformation);
                fabricClient.HealthManager.ReportHealth(healthReport);
                return(NodeAgentSfUtilityExitCodes.Success);
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.ErrorMessage(
                    String.Format("HealthManagerHelper.PostNodeHealthReport failed. Exception details {0}", e));
                if (e is FabricTransientException)
                {
                    return(NodeAgentSfUtilityExitCodes.RetryableException);
                }
                else
                {
                    return(NodeAgentSfUtilityExitCodes.Failure);
                }
            }
        }
Exemplo n.º 7
0
        public void ReportServiceHealth(ServiceContext serviceContext, HealthState healthState, string property)
        {
            HealthInformation   info   = new HealthInformation("Gateway", property, healthState);
            ServiceHealthReport health = new ServiceHealthReport(serviceContext.ServiceName, info);

            _fabricClient.HealthManager.ReportHealth(health);

            this.ServiceMessage(serviceContext, "Report health {0} {1}", property, healthState);
        }
        public void ReportServiceHealth(Actor actor, HealthState healthState, string property)
        {
            HealthInformation   info   = new HealthInformation("UserActorService", property, healthState);
            ServiceHealthReport health = new ServiceHealthReport(actor.ActorService.Context.ServiceName, info);

            _fabricClient.HealthManager.ReportHealth(health);

            this.ActorMessage(actor, "Report health {0} {1}", property, healthState);
        }
        /// <summary>
        /// Returns a health report
        /// </summary>
        /// <param name="context">The service fabric context that the health report is for</param>
        /// <param name="reportSourceId">The unique reporting source id</param>
        /// <param name="propertyName">The name of the health property being reported on</param>
        /// <param name="state">The current state of the health property</param>
        /// <param name="timeToLive">The time to live of the health report</param>
        /// <param name="reportType">The entity type the report is for</param>
        /// <returns>A health report for the appropriate reporting entity</returns>
        public static HealthReport GetHealthReport(ServiceContext context, string reportSourceId, string propertyName, HealthState state, ReportTypes reportType, TimeSpan timeToLive)
        {
            HealthReport report;
            var          information = new HealthInformation(reportSourceId, propertyName, state);

            information.Description       = $"{ propertyName } health state { Enum.GetName(typeof(HealthState), state) }";
            information.RemoveWhenExpired = true;
            information.TimeToLive        = timeToLive;
            information.SequenceNumber    = HealthInformation.AutoSequenceNumber;

            switch (reportType)
            {
            case ReportTypes.Cluster:
                report = new ClusterHealthReport(information);
                break;

            case ReportTypes.Application:
                report = new ApplicationHealthReport(new Uri(context.CodePackageActivationContext.ApplicationName), information);
                break;

            case ReportTypes.DeployedApplication:
                report = new DeployedApplicationHealthReport(new Uri(context.CodePackageActivationContext.ApplicationName), context.NodeContext.NodeName, information);
                break;

            case ReportTypes.Service:
                report = new ServiceHealthReport(context.ServiceName, information);
                break;

            case ReportTypes.DeployedService:
                report = new DeployedServicePackageHealthReport(new Uri(context.CodePackageActivationContext.ApplicationName), context.CodePackageActivationContext.GetServiceManifestName(), context.NodeContext.NodeName, information);
                break;

            case ReportTypes.Node:
                report = new NodeHealthReport(context.NodeContext.NodeName, information);
                break;

            case ReportTypes.Instance:
                if (context is StatelessServiceContext)
                {
                    report = new StatelessServiceInstanceHealthReport(context.PartitionId, context.ReplicaOrInstanceId, information);
                }
                else
                {
                    report = new StatefulServiceReplicaHealthReport(context.PartitionId, context.ReplicaOrInstanceId, information);
                }
                break;

            default:
                throw new ArgumentException("Unknown health type", nameof(reportType));
            }

            return(report);
        }
        private static void RegisterHealthEvent(string property, HealthState state, TimeSpan ttl)
        {
            HealthInformation information = new HealthInformation("X.Warmup", property, state)
            {
                Description       = "Concerning service startup",
                RemoveWhenExpired = true,
                TimeToLive        = ttl
            };
            HealthReport report = new ServiceHealthReport(serviceUri, information);

            client.HealthManager.ReportHealth(report);
        }
Exemplo n.º 11
0
        private void UpdateCoordinatorStatusHealthProperty(HealthState serviceHealthState, string description)
        {
            var hi = new HealthInformation(
                Constants.HealthReportSourceId,
                Constants.CoordinatorStatus,
                serviceHealthState)
            {
                Description = description,
            };

            var serviceUri   = this.factoryArgs.ServiceName;
            var healthReport = new ServiceHealthReport(serviceUri, hi);

            healthClient.ReportHealth(healthReport);
        }
        private void ReportHealthEvent(string description, HealthState healthState)
        {
            HealthInformation information = new HealthInformation()
            {
                HealthState       = healthState,
                Description       = description,
                Property          = "UpgradeStatus",
                RemoveWhenExpired = false,
                SourceId          = "System.UpgradeService",
            };

            ServiceHealthReport report = new ServiceHealthReport(this.serviceName, information);

            this.commandProcessor.FabricClient.HealthManager.ReportHealth(report);
        }
        private void ClearLegacyNotificationApprovalHealthStatus()
        {
            var hi = new HealthInformation(
                InfrastructureService.Constants.HealthReportSourceId,
                RoleInstanceHealthConstants.HealthReportManagementNotificationApprovalStatusPropertyName,
                HealthState.Ok)
            {
                Description       = "(Deprecated)",
                TimeToLive        = TimeSpan.FromSeconds(1),
                RemoveWhenExpired = true,
            };

            var serviceUri   = new Uri(this.environment.ServiceName);
            var healthReport = new ServiceHealthReport(serviceUri, hi);

            this.healthClient.ReportHealth(healthReport);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Reports health of all the Azure roleinstances corresponding to the Windows Fabric nodes
        /// to the Windows Fabric health store.
        /// </summary>
        /// <param name="validityPeriod">Serves as an indication to the watchdog as to how long the reported health is valid for.</param>
        public void ReportHealth(TimeSpan validityPeriod)
        {
            // start with an initial assumption that health is okay.
            const HealthState InputHealthState = HealthState.Ok;

            try
            {
                IList <RoleInstance> roleInstances = GetRoleInstances();

                HealthState serviceHealthState = roleInstances == null
                    ? HealthState.Warning
                    : GetRoleInstanceHealth(roleInstances, InputHealthState, healthPolicyManager);

                string description = GetServiceHealthDescription(roleInstances, serviceHealthState);

                // Specify a time to live. In case infrastructure service is down, the health report shows up as warning (or error)
                var hi = new HealthInformation(
                    HealthConstants.HealthReportSourceId,
                    HealthConstants.HealthReportReplicaHealthWatchdogStatus,
                    serviceHealthState)
                {
                    Description       = description,
                    TimeToLive        = validityPeriod != TimeSpan.Zero ? validityPeriod : TimeSpan.MaxValue,
                    RemoveWhenExpired = true
                };

                // Construct this name ourselves since there is currently a bug where the service Uri which
                // could have been passed in all the way from ServiceFactory's CreateReplica is an empty string.
                var serviceUri = new Uri(ServiceNamePrefix + coordinator.ConfigSectionName);

                // We'll roll up the health to the service level bypassing the replica and partition health.
                // Since only 1 replica is actively doing something and there is only a single partition of
                // this service, rolling up health higher is preferred since it can catch the user's eyes a
                // little bit faster.
                var healthReport = new ServiceHealthReport(serviceUri, hi);

                healthClient.ReportHealth(healthReport);
            }
            catch (Exception ex)
            {
                Trace.WriteWarning(
                    HealthConstants.TraceType,
                    "Unable to report health from role instance health watchdog. Error(s): {0}",
                    ex.GetMessage());
            }
        }
Exemplo n.º 15
0
        private async Task CheckEndpointAndReportHealthToCluster(HttpClient httpClient, KeyValuePair<string, string[]> service, string endpoint)
        {
            Logger.LogInformation($"Checking {service.Key} on endpoint {endpoint}");

            var healthEndpoint = $"{endpoint}/health";

            var httpResponse = await httpClient.GetAsync(healthEndpoint);

            if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK)
            {
                var responseBody = await httpResponse.Content.ReadAsStringAsync();
                Logger.LogInformation($"Error: {service.Key} on endpoint {endpoint} responded with '{responseBody}'");

                HealthState healthState = HealthState.Error;

                // Send report around the service health
                var serviceHealthReport = new ServiceHealthReport(
                    new Uri(service.Key),
                    new HealthInformation(
                        "Blanky-HealthWatchdog",
                        $"Healthendpoint ERROR returned {httpResponse.StatusCode.ToString()} on endpoint {endpoint}",
                        healthState));

                Client.HealthManager.ReportHealth(serviceHealthReport);
            }
            else
            {

                var responseBody = await httpResponse.Content.ReadAsStringAsync();
                Logger.LogInformation($"OK: {service.Key} on endpoint {endpoint} responded with '{responseBody}'");

                HealthState healthState = HealthState.Ok;

                // Send report around the service health
                var serviceHealthReport = new ServiceHealthReport(
                    new Uri(service.Key),
                    new HealthInformation(
                        "Blanky-HealthWatchdog",
                        $"Healthendpoint OK returned 200 on endpoint {endpoint}",
                        healthState));

                Client.HealthManager.ReportHealth(serviceHealthReport);
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Posts a health report against the current service to indicate status of Patch Orchestration Agent
        /// </summary>
        /// <param name="fabricClient">Fabric client object to carry out HM operations</param>
        /// <param name="serviceUri">Uri of the service against which health report is to be posted</param>
        /// <param name="healthReportProperty">Property of the health report</param>
        /// <param name="description">Description of the health report</param>
        /// <param name="healthState">HealthState for the health report</param>
        /// <param name="timeToLiveInMinutes">Time to live in minutes for health report</param>
        internal static void PostNodeHealthReport(FabricClient fabricClient, Uri serviceUri, string healthReportProperty, string description,
                                                  HealthState healthState, long timeToLiveInMinutes = -1)
        {
            HealthInformation healthInformation = new HealthInformation(SourceId, healthReportProperty,
                                                                        healthState)
            {
                RemoveWhenExpired = true,
                Description       = description
            };

            if (timeToLiveInMinutes >= 0)
            {
                healthInformation.TimeToLive = TimeSpan.FromMinutes(timeToLiveInMinutes);
            }

            ServiceHealthReport serviceHealthReport = new ServiceHealthReport(serviceUri, healthInformation);

            fabricClient.HealthManager.ReportHealth(serviceHealthReport);
        }
Exemplo n.º 17
0
        /// <summary>
        /// Suffix name to be appended with ApplicationName
        /// </summary>

        /// <summary>
        /// Posts a health report against Patch Orchestration Application's NodeAgentService
        /// </summary>
        /// <param name="fabricClient">Fabric client object to carry out HM operations</param>
        /// <param name="applicationName">Name of the application to construct servicename</param>
        /// <param name="serviceNameSuffix">serviceNameSuffix of the service to construct servicename</param>
        /// <param name="healthReportProperty">Property of the health report</param>
        /// <param name="description">Description of the health report</param>
        /// <param name="healthState">HealthState for the health report</param>
        /// <param name="timeToLiveInMinutes">Time to live in minutes for health report</param>
        /// <param name="timeout">Configured timeout for this operation.</param>
        internal static NodeAgentSfUtilityExitCodes PostServiceHealthReport(FabricClient fabricClient, Uri applicationName, string serviceNameSuffix, string healthReportProperty, string description,
                                                                            HealthState healthState, TimeSpan timeout, long timeToLiveInMinutes = -1)
        {
            HealthInformation healthInformation = new HealthInformation(SourceId, healthReportProperty,
                                                                        healthState)
            {
                RemoveWhenExpired = true,
                Description       = description
            };

            if (timeToLiveInMinutes >= 0)
            {
                healthInformation.TimeToLive = TimeSpan.FromMinutes(timeToLiveInMinutes);
            }

            try
            {
                ServiceHealthReport     healthReport = new ServiceHealthReport(new Uri(applicationName + serviceNameSuffix), healthInformation);
                HealthReportSendOptions sendOptions  = new HealthReportSendOptions();
                sendOptions.Immediate = true;
                fabricClient.HealthManager.ReportHealth(healthReport, sendOptions);

                Task.Delay(TimeSpan.FromSeconds(2)).GetAwaiter().GetResult();
                return(NodeAgentSfUtilityExitCodes.Success);
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.ErrorMessage(
                    String.Format("HealthManagerHelper.PostNodeHealthReport for Service {0} failed. Exception details {1}", serviceNameSuffix, e));
                if (e is FabricTransientException)
                {
                    return(NodeAgentSfUtilityExitCodes.RetryableException);
                }
                else if (e is TimeoutException)
                {
                    return(NodeAgentSfUtilityExitCodes.TimeoutException);
                }
                else
                {
                    return(NodeAgentSfUtilityExitCodes.Failure);
                }
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Posts a health report against the Node Agent Service.
        /// </summary>
        /// <param name="fabricClient">Fabric client to carry out HealthManager operation on cluster</param>
        /// <param name="serviceContext">Context of the current service</param>
        /// <param name="sourceId">SourceId for health report</param>
        /// <param name="healthReportProperty">Property of the health report</param>
        /// <param name="description">description of the health report</param>
        /// <param name="healthState">HealthState for the health report</param>
        /// <param name="timeToLiveInMinutes">Time to live for health report</param>
        internal static void PostServiceHealthReport(FabricClient fabricClient, ServiceContext serviceContext, string healthReportProperty, string description,
                                                     HealthState healthState, long timeToLiveInMinutes = -1)
        {
            HealthInformation healthInformation = new HealthInformation(SourceId, healthReportProperty,
                                                                        healthState);

            healthInformation.RemoveWhenExpired = true;
            healthInformation.Description       = description;
            if (timeToLiveInMinutes >= 0)
            {
                healthInformation.TimeToLive = TimeSpan.FromMinutes(timeToLiveInMinutes);
            }

            HealthReportSendOptions sendOptions = new HealthReportSendOptions();

            sendOptions.Immediate = true;

            ServiceHealthReport serviceInstanceHealthReport = new ServiceHealthReport(serviceContext.ServiceName, healthInformation);

            fabricClient.HealthManager.ReportHealth(serviceInstanceHealthReport, sendOptions);
        }
        public Task UpdateStatusAsync(string serviceName, string instance, string subStatusName, HealthStatus status, string message)
        {
            var healthInfo = new HealthInformation(
                GetType().FullName,
                subStatusName,
                MapStatus(status))
            {
                Description = message
            };

            System.Fabric.Health.HealthReport report;
            if (instance == null)
            {
                report = new ServiceHealthReport(
                    GetServiceUri(),
                    healthInfo
                    );
            }
            else if (_isStateful)
            {
                report = new StatefulServiceReplicaHealthReport(
                    _context.PartitionId,
                    _context.ReplicaOrInstanceId,
                    healthInfo
                    );
            }
            else
            {
                report = new StatelessServiceInstanceHealthReport(
                    _context.PartitionId,
                    _context.ReplicaOrInstanceId,
                    healthInfo
                    );
            }

            _fabricClient.HealthManager.ReportHealth(report, new HealthReportSendOptions {
                Immediate = true
            });
            return(Task.CompletedTask);
        }
Exemplo n.º 20
0
        /// <summary>
        /// This function generates Service Fabric Health Reports that will show up in SFX.
        /// </summary>
        /// <param name="healthReport">Utilities.HealthReport instance.</param>
        public void ReportHealthToServiceFabric(HealthReport healthReport)
        {
            if (healthReport == null)
            {
                return;
            }

            // There is no real need to change Immediate to true here for errors/warnings. This only adds unecessary stress to the
            // Health subsystem.
            var sendOptions = new HealthReportSendOptions {
                Immediate = false
            };

            // Quickly send OK (clears warning/errors states).
            if (healthReport.State == HealthState.Ok)
            {
                sendOptions.Immediate = true;
            }

            var timeToLive = TimeSpan.FromMinutes(5);

            if (healthReport.HealthReportTimeToLive != default)
            {
                timeToLive = healthReport.HealthReportTimeToLive;
            }

            TelemetryData healthData = healthReport.HealthData;

            string errWarnPreamble = string.Empty;

            if (healthReport.State == HealthState.Error ||
                healthReport.State == HealthState.Warning)
            {
                errWarnPreamble =
                    $"{healthReport.Observer} detected " +
                    $"{Enum.GetName(typeof(HealthState), healthReport.State)} threshold breach. ";

                // OSObserver does not monitor resources and therefore does not support related usage threshold configuration.
                if (healthReport.Observer == ObserverConstants.OSObserverName &&
                    healthReport.Property == "OSConfiguration")
                {
                    errWarnPreamble = $"{ObserverConstants.OSObserverName} detected potential problem with OS configuration: ";
                }
            }

            string message = $"{errWarnPreamble}{healthReport.HealthMessage}";

            if (healthData != null)
            {
                message = JsonConvert.SerializeObject(healthData);
            }

            if (string.IsNullOrEmpty(healthReport.SourceId))
            {
                healthReport.SourceId = healthReport.Observer;
            }

            if (string.IsNullOrEmpty(healthReport.Property))
            {
                switch (healthReport.Observer)
                {
                case ObserverConstants.AppObserverName:
                    healthReport.Property = "ApplicationHealth";
                    break;

                case ObserverConstants.CertificateObserverName:
                    healthReport.Property = "SecurityHealth";
                    break;

                case ObserverConstants.DiskObserverName:
                    healthReport.Property = "DiskHealth";
                    break;

                case ObserverConstants.FabricSystemObserverName:
                    healthReport.Property = "FabricSystemServiceHealth";
                    break;

                case ObserverConstants.NetworkObserverName:
                    healthReport.Property = "NetworkHealth";
                    break;

                case ObserverConstants.OSObserverName:
                    healthReport.Property = "MachineInformation";
                    break;

                case ObserverConstants.NodeObserverName:
                    healthReport.Property = "MachineResourceHealth";
                    break;

                default:
                    healthReport.Property = $"{healthReport.Observer}_HealthProperty";
                    break;
                }
                ;
            }

            var healthInformation = new HealthInformation(healthReport.SourceId, healthReport.Property, healthReport.State)
            {
                Description       = $"{message}",
                TimeToLive        = timeToLive,
                RemoveWhenExpired = true,
            };

            // Log health event locally.
            if (healthReport.EmitLogEvent)
            {
                if (healthReport.State == HealthState.Error)
                {
                    this.logger.LogError(healthReport.NodeName + ": {0}", healthInformation.Description);
                }
                else if (healthReport.State == HealthState.Warning)
                {
                    this.logger.LogWarning(healthReport.NodeName + ": {0}", healthInformation.Description);
                }
                else
                {
                    this.logger.LogInfo(healthReport.NodeName + ": {0}", healthInformation.Description);
                }
            }

            // To SFX.
            if (healthReport.ReportType == HealthReportType.Application && healthReport.AppName != null)
            {
                var appHealthReport = new ApplicationHealthReport(healthReport.AppName, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(appHealthReport, sendOptions);
            }
            else if (healthReport.ReportType == HealthReportType.Service && healthReport.ServiceName != null)
            {
                var serviceHealthReport = new ServiceHealthReport(healthReport.ServiceName, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(serviceHealthReport, sendOptions);
            }
            else if (healthReport.ReportType == HealthReportType.StatefulService &&
                     healthReport.PartitionId != Guid.Empty && healthReport.ReplicaOrInstanceId > 0)
            {
                var statefulServiceHealthReport = new StatefulServiceReplicaHealthReport(healthReport.PartitionId, healthReport.ReplicaOrInstanceId, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(statefulServiceHealthReport, sendOptions);
            }
            else if (healthReport.ReportType == HealthReportType.StatelessService &&
                     healthReport.PartitionId != Guid.Empty && healthReport.ReplicaOrInstanceId > 0)
            {
                var statelessServiceHealthReport = new StatelessServiceInstanceHealthReport(healthReport.PartitionId, healthReport.ReplicaOrInstanceId, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(statelessServiceHealthReport, sendOptions);
            }
            else if (healthReport.ReportType == HealthReportType.Partition && healthReport.PartitionId != Guid.Empty)
            {
                var partitionHealthReport = new PartitionHealthReport(healthReport.PartitionId, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(partitionHealthReport, sendOptions);
            }
            else if (healthReport.ReportType == HealthReportType.DeployedApplication && healthReport.AppName != null)
            {
                var deployedApplicationHealthReport = new DeployedApplicationHealthReport(healthReport.AppName, healthReport.NodeName, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(deployedApplicationHealthReport, sendOptions);
            }
            else
            {
                var nodeHealthReport = new NodeHealthReport(healthReport.NodeName, healthInformation);
                this.fabricClient.HealthManager.ReportHealth(nodeHealthReport, sendOptions);
            }
        }
        /// <summary>
        /// Returns a health report
        /// </summary>
        /// <param name="context">The service fabric context that the health report is for</param>
        /// <param name="reportSourceId">The unique reporting source id</param>
        /// <param name="propertyName">The name of the health property being reported on</param>
        /// <param name="state">The current state of the health property</param>
        /// <param name="timeToLive">The time to live of the health report</param>
        /// <param name="reportType">The entity type the report is for</param>
        /// <returns>A health report for the appropriate reporting entity</returns>
        public static HealthReport GetHealthReport(ServiceContext context, string reportSourceId, string propertyName, HealthState state, ReportTypes reportType, TimeSpan timeToLive)
        {
            HealthReport report;
            var information = new HealthInformation(reportSourceId, propertyName, state);

            information.Description = $"{ propertyName } health state { Enum.GetName(typeof(HealthState), state) }";
            information.RemoveWhenExpired = true;
            information.TimeToLive = timeToLive;
            information.SequenceNumber = HealthInformation.AutoSequenceNumber;

            switch (reportType)
            {
                case ReportTypes.Cluster:
                    report = new ClusterHealthReport(information);
                    break;

                case ReportTypes.Application:
                    report = new ApplicationHealthReport(new Uri(context.CodePackageActivationContext.ApplicationName), information);
                    break;

                case ReportTypes.DeployedApplication:
                    report = new DeployedApplicationHealthReport(new Uri(context.CodePackageActivationContext.ApplicationName), context.NodeContext.NodeName, information);
                    break;

                case ReportTypes.Service:
                    report = new ServiceHealthReport(context.ServiceName, information);
                    break;

                case ReportTypes.DeployedService:
                    report = new DeployedServicePackageHealthReport(new Uri(context.CodePackageActivationContext.ApplicationName), context.CodePackageActivationContext.GetServiceManifestName(), context.NodeContext.NodeName, information);
                    break;

                case ReportTypes.Node:
                    report = new NodeHealthReport(context.NodeContext.NodeName, information);
                    break;

                case ReportTypes.Instance:
                    if (context is StatelessServiceContext)
                    {
                        report = new StatelessServiceInstanceHealthReport(context.PartitionId, context.ReplicaOrInstanceId, information);
                    }
                    else
                    {
                        report = new StatefulServiceReplicaHealthReport(context.PartitionId, context.ReplicaOrInstanceId, information);
                    }
                    break;

                default:
                    throw new ArgumentException("Unknown health type", nameof(reportType));
            }

            return report;
        }