caproto.server.stats.PeriodicStatusHelper

class caproto.server.stats.PeriodicStatusHelper(*args, **kwargs)[source]

An IocStats-like tool for caproto IOCs. Includes values which update on a periodic basis (update_period, PV UPD_TIME).

PeriodicStatusHelper pvproperties

Attribute

Suffix

Docs

Type

Notes

Alarm Group

access

ACCESS

CA Security access level to this IOC

ENUM (mbbo)

ca_client_count

CA_CLNT_CNT

Number of CA clients [not implemented]

int (longin)

Read-only

ca_connection_count

CA_CONN_CNT

Number of CA Connections [not implemented]

int (longin)

Read-only

fd_count

FD_CNT

Allocated File Descriptors

int (ai)

Read-only

fd_free

FD_FREE

Available FDs

int (calc)

Read-only

fd_max

FD_MAX

Max File Descriptors

int (ai)

Read-only

heartbeat

HEARTBEAT

1 Hz counter since startup

int (calcout)

Read-only Startup

ioc_cpu_load

IOC_CPU_LOAD

float (ai)

Read-only

mem_free

MEM_FREE

Memory free (including swap).

int (ai)

Read-only

mem_max

MEM_MAX

int (ai)

Read-only

mem_used

MEM_USED

Memory used.

int (ai)

Read-only

num_threads

NumThreads

Number of threads in use

int (longin)

Read-only

record_count

RECORD_CNT

Number of records

int (ai)

Read-only

start_count

START_CNT

Startup count, if autosave is working

int (calcout)

Read-only Startup

start_tod

STARTTOD

Time and date of startup

str (stringin)

Read-only Length(100) Startup

susp_task_count

SUSP_TASK_CNT

Number of Suspended Tasks [not implemented]

int (longin)

Read-only

sys_cpu_load

SYS_CPU_LOAD

CPU load

float (ai)

Read-only

time_of_day

TOD

Current time and date

str (stringin)

Read-only Length(100) Startup

update_period

UPD_TIME

Basic stats update rate

float (ao)

Startup

uptime

UPTIME

Elapsed time since start

int (longin)

Read-only

Methods

group_read(instance)

Generic read called for channels without get defined

group_write(instance, value)

Generic write called for channels without put defined

Attributes

default_values

type_map

type_map_read_only

pvproperty methods

heartbeat.startup(self, instance, async_lib)
Source code: heartbeat.startup
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
            async def scanned_startup(group, prop, async_lib):
                if use_scan_field and period is not None:
                    if prop.field_inst.scan_rate_sec is None:
                        # This is a hook to allow setting of the default scan
                        # rate through the 'period' argument of the decorator.
                        prop.field_inst._scan_rate_sec = period
                        # TODO: update .SCAN to reflect this number

                sleep = async_lib.library.sleep
                while True:
                    t0 = time.monotonic()
                    if use_scan_field:
                        iter_time = prop.field_inst.scan_rate_sec
                        if iter_time is None:
                            iter_time = 0
                    else:
                        iter_time = period

                    if iter_time > 0:
                        await call_scan_function(group, prop, async_lib)
                    else:
                        iter_time = 0.1
                        # TODO: could the scan rate - or values in general -
                        # have events tied with them so busy loops are
                        # unnecessary?
                    elapsed = time.monotonic() - t0
                    sleep_time = (max(0, iter_time - elapsed)
                                  if subtract_elapsed
                                  else iter_time)
                    await sleep(sleep_time)

start_count.startup(self, instance, async_lib)
253
254
255
256
257
@start_count.startup
async def start_count(self, instance, async_lib):
    # Give autosave some time to load
    await async_lib.library.sleep(3)
    await self.start_count.write(value=self.start_count.value + 1)
start_tod.startup(self, instance, async_lib)
213
214
215
@start_tod.startup
async def start_tod(self, instance, async_lib):
    await self.start_tod.write(value=str(datetime.datetime.now()))
time_of_day.startup(self, instance, async_lib)
Source code: time_of_day.startup
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
            async def scanned_startup(group, prop, async_lib):
                if use_scan_field and period is not None:
                    if prop.field_inst.scan_rate_sec is None:
                        # This is a hook to allow setting of the default scan
                        # rate through the 'period' argument of the decorator.
                        prop.field_inst._scan_rate_sec = period
                        # TODO: update .SCAN to reflect this number

                sleep = async_lib.library.sleep
                while True:
                    t0 = time.monotonic()
                    if use_scan_field:
                        iter_time = prop.field_inst.scan_rate_sec
                        if iter_time is None:
                            iter_time = 0
                    else:
                        iter_time = period

                    if iter_time > 0:
                        await call_scan_function(group, prop, async_lib)
                    else:
                        iter_time = 0.1
                        # TODO: could the scan rate - or values in general -
                        # have events tied with them so busy loops are
                        # unnecessary?
                    elapsed = time.monotonic() - t0
                    sleep_time = (max(0, iter_time - elapsed)
                                  if subtract_elapsed
                                  else iter_time)
                    await sleep(sleep_time)

update_period.startup(self, instance, async_lib)
Source code: update_period.startup
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
    @update_period.startup
    async def update_period(self, instance, async_lib):
        self._startup_time = datetime.datetime.now()
        if resource is not None:
            try:
                soft_limit, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
                await self.fd_max.write(value=soft_limit)
            except Exception:
                self.log.warning('Failed to get maximum file descriptors')

        while True:
            try:
                await self._update()
            except Exception as ex:
                self.log.warning('Status update failure: %s', ex)
            await async_lib.library.sleep(self.update_period.value)