Tema anterior: Caso práctico 13: Tratamiento de un grupo de componente dinámicoTema siguiente: Ejemplos de escritura de lógica de negocios vigente


Caso práctico 14: Tratamiento del reloj de acumulación de tiempo

El patrón de diseño descrito en esta sección es apropiado cuando el resultado obligatorio es una función de un período de tiempo que ha pasado entre eventos, por ejemplo:

Para acumular tiempo es necesario asignar una variable en la que se pueda acumular tiempo (en segundos) e implementar una función que comprueba las dos condiciones y el tiempo acumulado desde que la última vez que se actualizó la hora. Esta función se ejecuta para todos los eventos recibidos para la fórmula.

La siguiente figura describe el tratamiento del reloj de acumulación de tiempo.

La variable LastUpdateTime se almacena la última vez que se realizó la actualización, independientemente de si el contador de tiempo se actualizó o no. La función mantiene la condición que determina si el tiempo debe actualizarse y acumularse. Por ejemplo, el tiempo no se debería tener en cuenta si se supera el período de ranura de tiempo, el estado del sistema era inactivo o el incidente tuvo un estado pendiente.

Aunque la situación detallada aquí a menudo utiliza la función Tools.NetTime() para calcular duraciones, puede haber casos en los que es preferible utilizar la función estándar VB DateDiff().

La función Tools.NetTime incurre en una sobrecarga de comprobación de la ranura de tiempo cada vez que se utiliza. Se recomienda evitar utilizar NetTime en los procedimientos de eventos de datos, ya que estos procedimientos se llaman para cualquier nuevo evento entrante y, por lo tanto, invocan la llamada NetTime. Si la ranura de tiempo es 24/7, es recomendable utilizar la función DateDiff para evitar la sobrecarga de comprobación de la ranura de tiempo.

Ejemplo 1:

La siguiente rutina de "contadores de actualización" acumula el período total de tiempo en la variable PeriodNetTime. En AvailabilityTime la rutina acumula el tiempo que el estado del sistema estuvo activo, lo que significa que el sistema estaba disponible.

El objeto Tools contiene el método NetTime, NetTime(beginTime, endTime)0. Este método devuelve el número de segundos entre beginTime y endTime que están dentro de la ranura de tiempo de la métrica actual. Cualquier momento entre estas dos variables forma parte de una ranura de tiempo que se excluye, por consiguiente, se utiliza muy a menudo para cálculos de duración en los que se utiliza una ranura de tiempo. (Por ejemplo: para los tickets de prioridad 1 resueltos en cuatro horas comerciales, donde incluso un ticket creado al final de un día laboral que no se puede resolver hasta la mañana siguiente está dentro del acuerdo de nivel de servicio debido a las horas de la ranura de tiempo que se excluyen.)

Sub UpdateCounters (time)
   PeriodNetTime = PeriodNetTime + tools.NetTime (LastUpdateTime, time)
   If SystemStatus = UP Then
      AvailabilityTime = AvailabilityTime + tools.NetTime (LastUpdateTime, time)
   End If
   LastUpdateTime = time
End Sub

Ejemplo 2:

El ejemplo siguiente calcula la disponibilidad de la aplicación al tratar los eventos de actividad e inactividad de varios componentes esenciales, así como los eventos de mantenimiento de dichos componentes. Si se está realizando el mantenimiento de todos los componentes, el tiempo no se considera como el tiempo previsto de disponibilidad.

La subrutina UpdateCounters adelanta los contadores tiempo cuando es necesario y se ejecuta con todos los eventos recibidos para la fórmula (evento de datos sin procesar/evento de motor). También actualiza el tiempo disponible previsto en los casos en los que el tiempo está dentro del período de ranura de tiempo y los componentes no están dentro de un período de tiempo de inactividad esperado. La fórmula actualiza el tiempo de disponibilidad real solamente cuando también tiene un estado "activo" del sistema.

DateDiff es una función de VB estándar que devuelve el tiempo entre dos fechas, pero no excluye ninguna información de ranura de tiempo.

'Imponer la declaración de la variable
Opción explícita

'Variables globales
Dim ExpectedAvailabilityTime
Dim ActualAvailabilityTime
Dim LastUpdateTime
Dim AvailabilityIndicators
Dim MonitoredComponents
Dim DowntimeStatuses

'Creación de objetos de asignación
Set AvailabilityIndicators=CreateObject("SlalomMap.Map")
Set MonitoredComponents=CreateObject("SlalomMap.Map")
Set DowntimeStatuses=CreateObject("SlalomMap.Map")

'Después de haberse cargado y siempre que ocurre un cambio de infraestructura
Sub OnRegistration(dispatcher)
   dispatcher.RegisterByResourceGroup "OnComponentDownEvent","Component Down","Application Components"
   dispatcher.RegisterByResourceGroup "OnComponentUpEvent","Component Up","Application Components"
   dispatcher.RegisterByResourceGroup "OnMaintenanceStartEvent","Maintenance Start","Application Components"
   dispatcher.RegisterByResourceGroup "OnMaintenanceEndEvent","Maintenance End","Application Components"
   UpdateCounters Context.RegistrationTime

   Dim AllocatedComponents
   Set AllocatedComponents = Context.ResourcesOfResourceGroup("Application Components")

   'Hay que asegurarse de que la fórmula se monitoriza solamente cuando es relevante y todos los recursos son relevantes
   UpdateMonitoredComponents AllocatedComponents
End Sub

Sub OnLoad(time)
   'Cuando el sistema está activo por primera vez: asumir que la disponibilidad es correcta
   LastUpdateTime = time
End Sub

Sub OnPeriodStart(time)
   'inicialización de contadores para renovar el cálculo periódico
   ExpectedAvailabilityTime = 0
   ActualAvailabilityTime = 0
End Sub

Sub OnTimeslotEnter(time)
   UpdateCounters time
End Sub

Sub OnTimeslotExit(time)
   UpdateCounters time
End Sub

Sub OnComponentDownEvent(eventDetails)
   UpdateCounters eventDetails.Time
   'escribir el estado de disponibilidad de los recursos sobre los que se informa
   AvailabilityIndicators(eventDetails.ResourceId) = _
      AvailabilityIndicators(eventDetails.ResourceId)+1
End Sub

Sub OnComponentUpEvent(eventDetails)
   UpdateCounters eventDetails.Time
   'escribir el estado de disponibilidad de los recursos sobre los que se informa
   AvailabilityIndicators(eventDetails.ResourceId)= _
      AvailabilityIndicators(eventDetails.ResourceId)-1
End Sub

Sub OnMaintenanceStartEvent(eventDetails)
   UpdateCounters eventDetails.Time
   'escribir el estado de disponibilidad de los recursos sobre los que se informa
   DowntimeStatuses(eventDetails.ResourceId)= _
      DowntimeStatuses(eventDetails.ResourceId)+1
End Sub

Sub OnMaintenanceEndEvent(eventDetails)
   UpdateCounters eventDetails.Time
   'escribir el estado de disponibilidad de los recursos sobre los que se informa
   DowntimeStatuses(eventDetails.ResourceId)= _
      DowntimeStatuses(eventDetails.ResourceId)-1
End Sub

Sub OnPeriodEnd(time,isComplete)
   UpdateCounters time
End Sub

Resultado de la función
   If ExpectedAvailabilityTime <> 0 Then
      Result = 100 * (ActualAvailabilityTime / ExpectedAvailabilityTime)
   Else
      Result = Null
   End If
End Function

Sub UpdateCounters(time)
   If Context.IsWithinTimeslot And Not AllComponentsAreInPlannedDowntime Then
      'actualizar contador de segundos en el período (cuando se espera la disponibilidad)
      ExpectedAvailabilityTime = ExpectedAvailabilityTime + DateDiff("s",LastUpdateTime,time)
      If SystemIsAvailable Then
         'actualizar contador de segundos de disponibilidad
         ActualAvailabilityTime = ActualAvailabilityTime + DateDiff("s",LastUpdateTime,time)
      End If
   End If
   LastUpdateTime=time
End Sub

Sub UpdateMonitoredComponents(allocatedComponents)
   Dim Component
   'añadir a la asignación de componentes controlados todos los nuevos componentes que hay que monitorizar
   For Each Component In allocatedComponents
      If Not MonitoredComponents.Exist(Component) Then
         MonitoredComponents(Component) = Component
         AvailabilityIndicators(Component) = 0
         DowntimeStatuses(Component) = 0
      End If
   Next

   'eliminar de la asignación de componentes controlados todos los componentes que ya no son relevantes
   For Each Component In MonitoredComponents
      If Not allocatedComponents.Exist(Component) Then
         MonitoredComponents.Erase Component
         AvailabilityIndicators.Erase Component
         DowntimeStatuses.Erase Component
      End If
   Next
End Sub

Function SystemIsAvailable
   Dim SystemAvailability
   SystemAvailability = True

   Dim Component
   Dim ComponentAvailability
   For Each Component In MonitoredComponents
      ComponentAvailability = AvailabilityIndicators(Component) = 0 _
         Or DowntimeStatuses(Component) > 0
      'la disponibilidad del sistema se evalúa con la disponibilidad
      SystemAvailability = SystemAvailability And ComponentAvailability
   Next
   SystemIsAvailable = SystemAvailability
End Function

Function AllComponentsAreInPlannedDowntime
   Dim ComponentsInPlannedDowntime
   ComponentsInPlannedDowntime = 0
   Dim Component
   For Each Component In MonitoredComponents
      If DowntimeStatuses(Component) > 0 Then
         ComponentsInPlannedDowntime = ComponentsInPlannedDowntime + 1
      End If
   Next

   If ComponentsInPlannedDowntime = MonitoredComponents.Count Then
      AllComponentsAreInPlannedDowntime = True
   Else
      AllComponentsAreInPlannedDowntime = False
   End If
End Function