Имплементация системы мониторинга кластеров 1С (и лицензий)

Администрирование - Системное

лицензии ras rac

46
В этой статье мы научимся хранить данные о сеансах консоли кластеров 1С в СУБД, вынимать и агрегировать информацию о лицензиях.
Имплементация системы мониторинга кластера 1С (и лицензий).
 
Для успешного приготовления нам потребуются:
  1. 1С Предприятие нужного Вам релиза.
  2. Linux* (я использую CentOS 7.5)
  3. Grafana* ( я использую версию 5.2.4)
  4. Postgres Pro* (у меня сейчас 10.6.1)
  5. Python (у меня 3.6.*)
 
*Вопросы установки LinuxGrafana и Postgre Pro в данной статье не будут рассмотрены.
 
 
Сначала коснёмся . Для сбора данных через RAS нам нужно:
 
  1. Установить(и запустить) службу RAS на серверах приложений 1С под Windows. Через RAS мы будем получать данные от этого СП . Установить службу можно сделать такой командой:
"C:\Windows\System32\sc.exe" create "1C:Remote Administation Serive (RAS)" binPath= "\"C:\Program Files\1cv8\8.3.12.1685\bin\ras.exe\" cluster --service --port=1545 ИМЯ_СЕРВЕРА:1540" start= auto
            Для автоматической установки службы RAS можно воспользоваться скриптом func.install_ras.ps1 из раздела загрузки.
 
  1. Установить необходимые компоненты rac на Linux.
     
    Для CentOS потребуется потребуется скачать с https://releases.1c.ru/  Сервер 1С:Предприятия (64-bit) для RPM-based Linux-систем.
    Порядок установки пакетов, на примере релиза 8.3.12.1685 для моей ОС следующий:
yum install -y 1C_Enterprise83-common-8.3.12-1685.x86_64.rpm
yum install -y 1C_Enterprise83-common-nls-8.3.12-1685.x86_64.rpm
yum install -y 1C_Enterprise83-server-8.3.12-1685.x86_64.rpm
yum install -y 1C_Enterprise83-server-nls-8.3.12-1685.x86_64.rpm
            После этого rac будет доступен из /opt/1C/v8.3/x86_64/rac.
 
  1. Проверить корректность установки можно подключившись к RAS.
/opt/1C/v8.3/x86_64/rac cluster list ИМЯ_СЕРВЕРА:1545
Если всё правильно, то мы увидим подобное:
 
 
Теперь подготовим отдельную базу в Postgre.
 
В ней нам потребуется несколько таблиц:
  1. Таблица для хранения списка серверов RAS, к которым мы будет подключаться за данными.
  2. Вспомогательные таблицы для экономии места
  3. Таблица данных о сеансах.
 
Подключаемся к postgre из консоли:
su postgres
psql
 
Создаём пользователя для работы со своей базой данных:
CREATE ROLE "racer" LOGIN PASSWORD 'my_evil_password';
 
Создаём отдельную базу данных:
CREATE DATABASE "racerDB"
WITH
  OWNER = "racer"
  ENCODING = 'UTF8'
  LC_COLLATE = 'ru_RU.UTF-8@icu.58.0.0.50'
  LC_CTYPE = 'ru_RU.UTF-8'
  TABLESPACE = "pg_default"
;
\connect racerDB;
 
Создаём таблицу для хранения списка RAS-серверов, к которым будем подключаться:
CREATE TABLE "public"."ras_servers" (
  "id" SERIAL PRIMARY KEY,
  "host_name" varchar(255) NOT NULL,
  "ras_port" int2 NOT NULL
);
ALTER TABLE "public"."ras_servers"
  OWNER TO "racer";
 
И заполняем её списком своих RAS-серверов:
INSERT INTO "public"."ras_servers"("host_name", "ras_port") VALUES ('ИМЯ_СЕРВЕРА_1', 1545) RETURNING *;
INSERT INTO "public"."ras_servers"("host_name", "ras_port") VALUES ('ИМЯ_СЕРВЕРА_2', 1545) RETURNING *;
...
INSERT INTO "public"."ras_servers"("host_name", "ras_port") VALUES ('ИМЯ_СЕРВЕРА_N', 1545) RETURNING *;
 
Теперь нам нужно создать несколько служебных таблиц, чтобы хранить в них ссылки на данные из главной таблицы соединений.
 
  • Таблица для хранения списка пользователей
CREATE TABLE "public"."users" (
  "id" SERIAL PRIMARY KEY,
  "name" varchar(255) NOT NULL
);
ALTER TABLE "public"."users"
  OWNER TO "racer";
 
  • Таблица со списком информационных баз
CREATE TABLE "public"."infobases" (
  "id" SERIAL PRIMARY KEY,
  "uuid"  varchar(36) NOT NULL,
  "name"  varchar(255) NOT NULL,
  "descr" varchar(1024)
);
ALTER TABLE "public"."infobases"
  OWNER TO "racer";
 
  • Таблица со списком клиентских ПК
CREATE TABLE "public"."hosts" (
  "id" SERIAL PRIMARY KEY,
  "name" varchar(255) NOT NULL
);
ALTER TABLE "public"."hosts"
  OWNER TO "racer";
 
  • Таблица со списком лицензий
CREATE TABLE "public"."licenses_db" (
  "id" SERIAL PRIMARY KEY,
  "name" varchar(255) NOT NULL,
  "type" varchar(4)   NOT NULL,
  "max"  int2         NOT NULL
);
ALTER TABLE "public"."licenses_db"
  OWNER TO "racer";
 
  • Таблица со списком приложений
CREATE TABLE "public"."apps" (
  "id" SERIAL PRIMARY KEY,
  "name" varchar(255) NOT NULL,
  "description" varchar(255)
);
ALTER TABLE "public"."apps"
  OWNER TO "racer";
--и сразу заполним её
INSERT INTO "public"."apps"("name", "description") VALUES ('1CV8', 'Толстый клиент') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('1CV8C', 'Тонкий клиент') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('WebClient', 'Веб-клиент') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('Designer', 'Конфигуратор') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('COMConnection', 'COM-соединение') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('WSConnection', 'Сессия веб-сервиса') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('BackgroundJob', 'Фоновое задание') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('SystemBackgroundJob ', 'Системное фоновое задание') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('SrvrConsole', 'Консоль кластера') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('COMConsole', 'COM-консоль кластера') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('JobScheduler ', 'Планировщик') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('Debugger', 'Отладчик') RETURNING *;
INSERT INTO "public"."apps"("name", "description") VALUES ('RAS', 'Сервер администрирования') RETURNING *;
 
  • Таблица со списком процессов сервера . В ней будет храниться неизменяемая информация о процессах СП (она нужна нам для получения имени рабочего сервера для сессии)
CREATE TABLE "public"."processes" (
  "id" SERIAL PRIMARY KEY,
  "uuid" varchar(36) NOT NULL,
  "host" varchar(255),
  "port" int4,
  "pid"  int4,
  "started_at"  timestamp
);
ALTER TABLE "public"."processes"
  OWNER TO "racer";
 
Теперь создаём таблицу, в которой будем хранить информацию о соединениях и их лицензиях.
CREATE TABLE "public"."sessions" (
    "ras_server_by_id"                  int2        NOT NULL,                               --ссылка на имя RAS-сервера, с которого были получены данные
    FOREIGN KEY("ras_server_by_id")     REFERENCES  hosts(id)       ON DELETE SET DEFAULT,  --ссылка на имя RAS-сервера, с которого были получены данные
    "datetime"                          timestamp   NOT NULL,                               --дата и время получения среза в UTC
    "session-id_nmb"                    int4        NOT NULL,                               --номер сессии
    "infobase_by_id"                    int2        NOT NULL,                               --id информационной базы из таблицы infobases
    FOREIGN KEY("infobase_by_id")       REFERENCES infobases(id)    ON DELETE SET DEFAULT,  --id информационной базы из таблицы infobases
    "process_by_id"                     int4                ,                               --id процесс СП 1C из таблицы processes
    FOREIGN KEY("process_by_id")        REFERENCES  processes(id)   ON DELETE SET DEFAULT,  --id процесс СП 1C из таблицы processes
    "user-name_by_id"                   int2        NOT NULL,                               --id пользователя из таблицы users
    FOREIGN KEY("user-name_by_id")      REFERENCES  users(id)       ON DELETE SET DEFAULT,  --id пользователя из таблицы users
    "host_by_id"                        int2        NOT NULL,                               --id хоста пользователя
    FOREIGN KEY("host_by_id")           REFERENCES  hosts(id)       ON DELETE SET DEFAULT,  --id хоста пользователя
    "app-id_by_id"                      int2        NOT NULL,                               --id приложения из таблицы apps
    FOREIGN KEY("app-id_by_id")         REFERENCES  apps(id)        ON DELETE SET DEFAULT,  --id приложения из таблицы apps
    "started-at"                        timestamp   NOT NULL,                               --дата и время начала сеанса в UTC
    "last-active-at"                    timestamp   NOT NULL,                               --последняя активность
    "hibernate"                         bool        NOT NULL,                               --спящий ли сеанс
    "passive-session-hibernate-time"    int4        NOT NULL,                               --
    "hibernate-session-terminate-time"  int4        NOT NULL,                               --
    "blocked-by-dbms"                   int4        NOT NULL,                               --
    "blocked-by-ls"                     int4        NOT NULL,                               --
    "bytes-all"                         int8        NOT NULL,                               --
    "bytes-last-5min"                   int8        NOT NULL,                               --
    "calls-all"                         int4        NOT NULL,                               --
    "calls-last-5min"                   int4        NOT NULL,                               --
    "dbms-bytes-all"                    int8        NOT NULL,                               --
    "dbms-bytes-last-5min"              int8        NOT NULL,                               --
    "db-proc-info"                      int4        NOT NULL,                               --
    "db-proc-took"                      int4        NOT NULL,                               --
    "db-proc-took-at"                   timestamp           ,                               --
    "duration-all"                      int4        NOT NULL,                               --
    "duration-all-dbms"                 int4        NOT NULL,                               --
    "duration-current"                  int4        NOT NULL,                               --
    "duration-current-dbms"             int4        NOT NULL,                               --
    "duration-last-5min"                int4        NOT NULL,                               --
    "duration-last-5min-dbms"           int4        NOT NULL,                               --
    "memory-current"                    int8        NOT NULL,                               --
    "memory-last-5min"                  int8        NOT NULL,                               --
    "memory-total"                      int8        NOT NULL,                               --
    "read-current"                      int8        NOT NULL,                               --
    "read-last-5min"                    int8        NOT NULL,                               --
    "read-total"                        int8        NOT NULL,                               --
    "write-current"                     int8        NOT NULL,                               --
    "write-last-5min"                   int8        NOT NULL,                               --
    "write-total"                       int8        NOT NULL,                               --
    "duration-current-service"          int4        NOT NULL,                               --
    "duration-last-5min-service"        int4        NOT NULL,                               --
    "duration-all-service"              int4        NOT NULL,                               --
    "license_by_id"                     int2                ,                               --размер ключа (на сколько он пользователей)
    FOREIGN KEY("license_by_id")        REFERENCES licenses_db(id)  ON DELETE SET DEFAULT,  --размер ключа (на сколько он пользователей)
    "license_issued_by_server"          bool                ,                               --признак выдачи лицензии сервером
    "license_net"                       bool                ,                               --сетевая ли лицензия
    "rmngr_by_id"                       int2                ,                               --хост, выдавший лицензию
    FOREIGN KEY("rmngr_by_id")          REFERENCES hosts(id)        ON DELETE SET DEFAULT   --хост, выдавший лицензию
);
ALTER TABLE "public"."sessions"
  OWNER TO "racer";
 
CREATE INDEX "by_date" ON "public"."sessions" USING btree (
  "datetime" "pg_catalog"."timestamp_ops" ASC NULLS LAST
);
 
Так как в таблице хранятся ссылки, а не абсолютные значения, создадим для удобства просмотров, агрегированный view_sessions, содержащий значения всех всех собранных данных:
CREATE VIEW "public"."view_sessions" AS
SELECT
     h1.name                                AS ras_host
   , s.datetime                             AS datetime
   , s."session-id_nmb"                     AS session_id
   , i.name                                 AS infobase_name
   , p.host                                 AS process_host
   , p.port                                 AS process_port
   , p.pid                                  AS process_pid
   , p.started_at                           AS process_started
   , u.name                                 AS user_name
   , h2.name                                AS user_host
   , a.name                                 AS app
   , s."started-at"                         AS started_at
   , s."last-active-at"                     AS last_active_at
   , s.hibernate                            AS hibernate
   , s."passive-session-hibernate-time"     AS passive_session_hibernate_time
   , s."hibernate-session-terminate-time"   AS hibernate_session_terminate_time
   , s."blocked-by-dbms"                    AS blocked_by_dbms
   , s."blocked-by-ls"                      AS blocked_by_ls
   , s."bytes-all"                          AS bytes_all
   , s."bytes-last-5min"                    AS bytes_last_5min
   , s."calls-all"                          AS calls_all
   , s."calls-last-5min"                    AS calls_last_5min
   , s."dbms-bytes-all"                     AS dbms_bytes_all
   , s."dbms-bytes-last-5min"               AS dbms_bytes_last_5min
   , s."db-proc-info"                       AS db_proc_info
   , s."db-proc-took"                       AS db_proc_took
   , s."db-proc-took-at"                    AS db_proc_took_at
   , s."duration-all"                       AS duration_all
   , s."duration-all-dbms"                  AS duration_all_dbms
   , s."duration-current"                   AS duration_current
   , s."duration-current-dbms"              AS duration_current_dbms
   , s."duration-last-5min"                 AS duration_last_5min
   , s."duration-last-5min-dbms"            AS duration_last_5min_dbms
   , s."memory-current"                     AS memory_current
   , s."memory-last-5min"                   AS memory_last_5min
   , s."memory-total"                       AS memory_total
   , s."read-current"                       AS read_current
   , s."read-last-5min"                     AS read_last_5min
   , s."read-total"                         AS read_total
   , s."write-current"                      AS write_current
   , s."write-last-5min"                    AS write_last_5min
   , s."write-total"                        AS write_total
   , s."duration-current-service"           AS duration_current_service
   , s."duration-last-5min-service"         AS duration_last_5min_service
   , s."duration-all-service"               AS duration_all_service
   , l.name                                 AS license_series
   , l.type                                 AS license_type
   , l.max                                  AS license_max
   , s.license_issued_by_server             AS license_issued_by_server
   , s.license_net                          AS license_net
   , h3.name                                AS license_rmngr
FROM
     sessions         s
LEFT JOIN hosts       h1                    ON s.ras_server_by_id   = h1.id
LEFT JOIN infobases   i                     ON s.infobase_by_id     = i.id
LEFT JOIN processes   p                     ON s.process_by_id      = p.id
LEFT JOIN users       u                     ON s."user-name_by_id"  = u.id
LEFT JOIN hosts       h2                    ON s.host_by_id         = h2.id
LEFT JOIN apps        a                     ON s."app-id_by_id"     = a.id
LEFT JOIN licenses_db l                     ON s.license_by_id      = l.id
LEFT JOIN hosts       h3                    ON s.rmngr_by_id        = h3.id
;
ALTER TABLE "public"."view_sessions"
  OWNER TO "racer";
 
Для выборки данных о лицензиях нам понадобится отдельный View, ибо с использованием лицензий не всё так просто.
утилизирует лицензии полученные клиентом и выданные сервером по разному:
  • при выдаче сервером для каждого сеанса выдаётся одна программная лицензия;
  • при выдаче сервером для каждого сеанса выдаётся одна аппаратная лицензия;
  • при выдаче клиентскому приложению службой HASP LM для каждого пользовательского сеанса(сессия RDP или локальное подключение Windows) на клиенте выдаётся одна аппаратная лицензия. При этом с этой одной лицензией можно работать в разных базах.
  • как считать программные лицензии, полученные локально клиентским приложением я ещё не определился, к ним применяется такой же порядок, как для аппаратных, выданных клиенту.
 
Из-за этих особенностей в отборе применяется три вида группировки:
  • для серверов, не являющихся  терминальными (отбираются через view_not_terminal_ids) агрегируются все подключения с каждого хоста для каждого уникального ключа;
  • для терминальных серверов (view_terminal_ids) применяется дополнительная агрегация и по имени пользователя - применяется допущение, что пользователь, работающий из терминальной сессии в разных базах, будет работать там под одним именем;
  • и наконец, для лицензий, выданных сервером, не применяется никакой группировки.
 
Сначала определимся со списком рабочих станций, не являющихся терминальными серверами:
CREATE VIEW view_not_terminal_ids AS
SELECT h.id from HOSTS h
WHERE
            (UPPER (( h.NAME ) :: TEXT ) !~~ 'TERM%' :: TEXT)
            AND
            (UPPER (( h.NAME ) :: TEXT ) !~~ 'APP%' :: TEXT)
;
ALTER TABLE "public"."view_not_terminal_ids"
  OWNER TO "racer";
 
Потом - со списком терминальных серверов:
CREATE VIEW view_terminal_ids AS
SELECT h.id from HOSTS h
WHERE
            (UPPER (( h.NAME ) :: TEXT ) ~~ 'TERM%' :: TEXT)
            OR
            (UPPER (( h.NAME ) :: TEXT ) ~~ 'APP%' :: TEXT)
;
ALTER TABLE "public"."view_terminal_ids"
  OWNER TO "racer";
 
Теперь можно создавать View с группировкой использования лицензий:
CREATE VIEW "public"."view_licenses" AS
SELECT
    s.datetime
  , '' :: TEXT                  AS user_name
  , UPPER (( h.NAME ) :: TEXT ) AS user_host
  , '' :: TEXT                  AS appid
  , l.NAME                      AS license_series
  , s.license_issued_by_server  AS license_issued_by_server
  , s.license_net               AS license_net
  , l.TYPE                      AS license_type
  , ''                          AS license_rmngr                --у клиентских не будет RMNGR
  , l.MAX                       AS license_max
  , COUNT ( * )                 AS seanses_count                --сеансов на эту лицензию
FROM
    sessions    s
LEFT JOIN hosts       h         ON s.host_by_id        = h.ID
LEFT JOIN licenses_db l         ON s.license_by_id     = l.ID
LEFT JOIN users       u         ON s."user-name_by_id" = u.ID
WHERE
    (s.license_issued_by_server = FALSE)                        --только лицензии, не выданные сервером
    AND
    (s.host_by_id in (select id from view_not_terminal_ids))    --и не с терминальных серверов
GROUP BY                                                        --группируем по
    s.datetime
  , ( UPPER (( h.NAME ) :: TEXT ))                              --имени хоста
  , l.NAME                                                      --серии лицензии
  , s.license_issued_by_server                                  --признаку выдачи сервером
  , s.license_net                                               --является ли лицензия сетевой
  , l.TYPE                                                      --типу - приграммная/аппаратная
  , l.MAX                                                       --размеру ключа
 
UNION ALL
SELECT
    s.datetime
  , UPPER (( u.NAME ) :: TEXT ) AS user_name
  , UPPER (( h.NAME ) :: TEXT ) AS user_host
  , '' :: TEXT                  AS appid
  , l.NAME                      AS license_series
  , s.license_issued_by_server  AS license_issued_by_server
  , s.license_net               AS license_net
  , l.TYPE                      AS license_type
  , ''                          AS license_rmngr                --у клиентских не будет RMNGR
  , l.MAX                       AS license_max
  , COUNT ( * )                 AS seanses_count                --сеансов на эту лицензию
FROM
    sessions    s
LEFT JOIN hosts       h         ON s.host_by_id        = h.ID
LEFT JOIN licenses_db l         ON s.license_by_id     = l.ID
LEFT JOIN users       u         ON s."user-name_by_id" = u.ID
WHERE
    (s.license_issued_by_server = FALSE)                        --только лицензии, не выданные сервером
    AND
    (s.host_by_id in (select id from view_terminal_ids))        --с терминальных серверов
GROUP BY
    s.datetime
  , ( UPPER (( u.NAME ) :: TEXT ))                              --добавляем группировку по имени пользователя
  , ( UPPER (( h.NAME ) :: TEXT ))                              --имени хоста
  , l.NAME                                                      --серии лицензии
  , s.license_issued_by_server                                  --признаку выдачи сервером
  , s.license_net                                               --является ли лицензия сетевой
  , l.TYPE                                                      --типу - приграммная/аппаратная    
  , l.MAX                                                       --размеру ключа
 
UNION ALL
SELECT
    s.datetime
  , UPPER (( u.NAME ) :: TEXT ) AS user_name
  , UPPER (( h.NAME ) :: TEXT ) AS user_host
  , A.NAME                      AS appid
  , l.NAME                      AS license_series
  , s.license_issued_by_server  AS license_issued_by_server
  , s.license_net               AS license_net
  , l.TYPE                      AS license_type
  , UPPER (( h2.NAME ) :: TEXT )AS license_rmngr                --а здесь RMNGR будет
  , l.MAX                       AS license_max
  , '1' :: BIGINT               AS seanses_count                --сеансов на эту лицензию
FROM
    sessions    s
LEFT JOIN hosts       h         ON s.host_by_id        = h.ID
LEFT JOIN licenses_db l         ON s.license_by_id     = l.ID
LEFT JOIN users       u         ON s."user-name_by_id" = u.ID
LEFT JOIN apps        a         ON s."app-id_by_id"    = A.ID
LEFT JOIN hosts       h2        ON s.rmngr_by_id       = h2.ID    
WHERE
    s.license_issued_by_server = TRUE                           --все лицензии выданные сервером не группируются
;
ALTER TABLE "public"."view_licenses"
  OWNER TO "racer";
 
Подготовка хранилища данных завершена.
 
 
Собираем данные
 
Сначала о командах, используемых для получения информации:
  • /opt/1C/v8.3/x86_64/rac cluster list                                                              ИМЯ_СЕРВЕРА:1545   #так мы будем получать список кластеров из сервера RAS
  • /opt/1C/v8.3/x86_64/rac infobase summary list --cluster=GUID_Кластера ИМЯ_СЕРВЕРА:1545   #здесь мы, используя GUID кластера из первой команды, получим список баз
  • /opt/1C/v8.3/x86_64/rac process list                  --cluster=GUID_Кластера ИМЯ_СЕРВЕРА:1545   #а так мы получим информацию о списке рабочих процессов
  • /opt/1C/v8.3/x86_64/rac session list                  --cluster=GUID_Кластера ИМЯ_СЕРВЕРА:1545    #с помощью этой команды можно получить список сеансов, но здесь есть не вся информация о лицензии
  • /opt/1C/v8.3/x86_64/rac session list --licenses  --cluster=GUID_Кластера ИМЯ_СЕРВЕРА:1545   #а тут мы получаем недостающую информацию о лицензиях
 
Общий порядок работы скрипта такой:
  1. Получаем список кластеров сервера RAS из таблицы ras_servers в базе Postre
  2. Получаем список информационных баз кластера
  3. Получаем список процессов кластера
  4. Получаем список сеансов и их лицензий
  5. Сводим все данные и заносим в целевую таблицу
 
Проверим, что у нас установлен Python 3.6
yum list installed | grep python36
 
Если его нет, то нужно его поставить:
yum install -y https://centos7.iuscommunity.org/ius-release.rpm
yum install -y python36u python36u-devel python36u-pip
 
И, в любом случае, нужно поставить два используемых модуля Python:
pip3.6 install psycopg2
pip3.6 install pytz
 
После этого нужно настроить скрипт сбора данных (см. раздел загружаемых файлов) - отредактировать его и поменять параметры подключения к Postre.
postgre_host                     = "localhost"
postgre_port                     = "5432"
postgre_database                 = "racerDB"
postgre_database_user            = "racer"
postgre_database_user_password   = "password"
 
И проверить корректность всех настроек, запустив его сразу из консоли:
/usr/bin/python3.6 /root/pyrac1c.py
 
Если до этого всё сделано правильно, то можно его в планировщик:
crontab -l | { while IFS= read -ra tasks; do printf '%s\n' "$tasks"; done; echo '*/10 * * * * /usr/bin/python3.6 /root/pyrac1c.py > /dev/null 2>&1';} | crontab #добавляем к списку заданий /usr/bin/python3.6 /root/pyrac1c.py для запуска через каждые 10 минут
 
 
У нас уже начали собираться данные, самое время отправиться в Grafana и настроить графики.
 
Сначала нужно добавить новый DataSource с типом PostgreSQL и данными для подключения к нашему серверу с данными:
 
После этого можно смело создавать новый Dashboard и добавлять на него первый Graph
 
Выбираете свой Datasource на вкладке Metrics и можно редактировать тексты запросов.
 
В качестве первого запроса агрегируем информацию об утилизации лицензий:
--всего утилизировано лицензий
SELECT
  $__timeGroup(DATETIME, '10m',0) as "time",
  --DATETIME,
  COUNT(*) AS "Утилизировано лиц. всего."
FROM view_licenses l
GROUP BY l.datetime
ORDER BY l.datetime asc
 
Сделаем отдельный график для лицензий, утилизированный сервером и клиентом :
--утилизировано серверных и клиентских
SELECT  
    $__timeGroup(l.datetime, '10m',0),
    --l.datetime,
    CASE
        WHEN l.license_issued_by_server=true THEN 'Утилизировано серверных'
        WHEN l.license_issued_by_server=false THEN 'Утилизировано клиентских'
    END,
    COUNT(*)
FROM view_licenses l
GROUP BY l.datetime,l.license_issued_by_server
ORDER BY l.datetime asc
 
Узнаем, сколько же всего у нас сеансов с лицензий:
--сеансы с лицензией
SELECT
    $__timeGroup(s.datetime,10m,0),
    --s.datetime,
    COUNT(*) as "Сеансов с лицензией"
FROM
    sessions s
WHERE s.license_by_id is not null
GROUP BY s.datetime
ORDER BY s.datetime
 
И сколько из них получило лицензию на сервере или на клиенте:
--сеансы с программными или аппаратными лицензиями
SELECT  
    $__timeGroup(s.datetime, '10m',0),
    --s.datetime,
    CASE
        WHEN s.license_issued_by_server=true THEN 'Сеансов с лицензией от сервера'
        WHEN s.license_issued_by_server=false THEN 'Сеансов с лицензий от клиента'
    END,
    COUNT(*)
FROM sessions s
WHERE s.license_issued_by_server is not null and s.license_by_id is not null
GROUP BY s.datetime,s.license_issued_by_server
ORDER BY s.datetime asc
 
Отдельный график можно сделать и по сеансам с программными и аппаратными лицензиями:
--Сеансы программных и аппаратных лицензий
SELECT  
  $__timeGroup(DATETIME, '10m',0),
  --s.DATETIME,
  'Сеансов с лицензией '||l.type,
  COUNT(*)
FROM
  sessions s, licenses_db l
where l.id = s.license_by_id
GROUP BY s.datetime,l.type
ORDER BY s.datetime asc
 
И посмотреть утилизацию ключей по типам (обратите внимание, что многопользовательские ключи на 20, 50 и 100 лицензий обладают одинаковым идентификатором - ORGL8. А ещё для клиентских лицензий мы не может узнать какой HASP LM их выдал, поэтому они агрегируются сразу по всем ключам одного типа и значение для графика таких ключей может быть больше ёмкости одного ключа):
--утилизацию по типам ключей
SELECT
    $__timeGroup(l.datetime,10m, 0) AS "time"
    --l.datetime as datetime
        ,case
            when l.license_issued_by_server then
                    'server '||l.license_type||'-'||l.license_series||'('||l.license_max||') by '|| l.license_rmngr
            else
                    'client '||l.license_type||'-'||l.license_series||'('||l.license_max||')'
    end AS license_data
        ,count(*)
FROM view_licenses l
GROUP BY l.datetime,license_data
ORDER BY l.datetime,license_data asc
 
Напоследок, можем посмотреть и сколько у нас спящих сеансов:
--спящие сеансы
SELECT
    $__timeGroup(s.datetime,10m,0),
    --s.datetime,
    COUNT(*) as "Спящие сеансы"
FROM
    sessions s
WHERE s.hibernate = TRUE
GROUP BY s.datetime
ORDER BY s.datetime
 
На выходе получаются вот такие прекрасные графики.
 
 
 
 
 
 
46

Скачать файлы

Наименование Файл Версия Размер
Скрипт сбора данных о сеансах в Postgre
.py 55,27Kb
30.11.18
2
.py 1.01 55,27Kb 2 Скачать
Скрипт автоматического создания службы RAS
.ps1 3,67Kb
30.11.18
1
.ps1 3,67Kb 1 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. asved.ru 36 03.12.18 07:55 Сейчас в теме
Весь процесс сбора данных есть в ЦКК. Немного его допиливаем, а логику аггрегации лицензий выносим в отчет. Или в алгоритм заполнения мониторинговой БД, если используется сторонняя система мониторинга. В частности, я шлю в Zabbix посредством ВК, реализующей Zabbix sender.
3. tvm 03.12.18 09:15 Сейчас в теме
(1) а зачем через ВК в Zabbix слать? Он может сам дергать агента и получать инфу
6. asved.ru 36 03.12.18 15:48 Сейчас в теме
(3) Так экономнее: агент сам по себе в 1С ходить не умеет, типовое решение - агент читает stdout дочернего процесса. Который еще нужно запустить, потратив на это системные ресурсы.
7. tvm 03.12.18 16:10 Сейчас в теме
(6) если агентом дергать rac- не сильно то и затратнее
2. Mortum 03.12.18 08:10 Сейчас в теме
Хороший, навороченный, но сложный велосипед.
kauksi; MrWonder; +2 Ответить
4. MrWonder 285 03.12.18 09:19 Сейчас в теме
(2) Спасибо за оценку. Я поэтому и описал подробно, чтобы самому всё уложить в голове )))
5. capitan 757 03.12.18 14:06 Сейчас в теме
Может это и велосипед, не знаю.
Но велосипед боевой )
Как совет - по хорошему надо просто серверам ограничить доступ к аппаратным лицензиям.
Уберете путаницу и количество свободных лицензий увеличите
Оставьте свое сообщение