Создание информационной панели для мониторинга ключевых параметров СЭД на основе системы отчетов Microsoft SQL Server Reporting Services
На сегодняшний день трендом в области визуализации цифровых данных являются так называемые информационные панели (dashboard), позволяющие отслеживать одновременно ряд ключевых показателей работы объекта. Большинство подобных панелей представляют собой верхний срез систем аналитики, характеризующий результаты работы наблюдаемого объекта, дающий необходимую информацию для принятия решений. Удобство применения информационных панелей во многом определяется их свойствами:
Применимость таких решений практически ко всем системам, позволяющим в автоматизированном режиме группировать и анализировать данные, а также удобство использования в процессе выработки решений предопределяет их растущую популярность. Не составляют исключение и системы электронного документооборота (далее – СЭД), которые также могут быть объектом мониторинга. К СЭД, помимо прочего, применимы традиционные показатели:
Ввиду того, что сервером базы данных для СЭД Directum является Microsoft SQL Server, в качестве системы отчетов для создания информационной панели удобно использовать Microsoft SQL Server Reporting Services (далее - SSRS). Для этого потребуются следующие компоненты:
Настройка SSRS и подключение построителя отчетов не имеет нюансов и выполняется в соответствии с инструкцией компании-производителя программного обеспечения в библиотеке MSDN: https://msdn.microsoft.com/ru-ru/library/bb630430(v=sql.120).aspx
Для подготовки информационной панели сервера СЭД может быть предложен набор следующих показателей:
Для сбора необходимых сведений используем запросы T-SQL к серверу баз данных СЭД:
Длительность сессий пользователей
WITH t1 ( Login_Name ,MessageBox ) AS ( SELECT Login_Name ,CASE WHEN DATEDIFF(HOUR, MIN(Login_Time), GETDATE()) <= 1 THEN 'INFO (less 1 hour)' WHEN DATEDIFF(HOUR, MIN(Login_Time), GETDATE()) = 2 THEN 'WARNING (between 1 and 2 hours)' WHEN DATEDIFF(HOUR, MIN(Login_Time), GETDATE()) >= 3 THEN 'ALERT (more 3 hours)' END AS MessageBox FROM sys.dm_exec_sessions WHERE database_id > 0 AND DB_NAME(database_id) IN ('DIRECTUM') AND Login_name NOT IN ( 'sa' ,'ISBuilderSystem' ,'Conductor' ) GROUP BY Login_Name ) SELECT MessageBox ,COUNT(MessageBox) AS CountMB FROM t1 GROUP BY MessageBox
Состояние индексов таблиц базы данных СЭД
SELECT TOP 15 OBJECT_NAME(s.[object_id]) AS TableName ,i.NAME AS IndexName ,ROUND(avg_fragmentation_in_percent, 2) AS FragmentationPercent ,SUM(pr.Rows) AS Row_count FROM sys.dm_db_index_physical_stats(db_id(), NULL, NULL, NULL, NULL) s INNER JOIN sys.indexes AS i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id LEFT JOIN sys.partition_schemes AS p ON i.data_space_id = p.data_space_id LEFT JOIN sys.objects o ON s.[object_id] = o.[object_id] LEFT JOIN sys.schemas AS sh ON sh.[schema_id] = o.[schema_id] JOIN sys.partitions pr ON i.object_id = pr.object_id AND i.index_id = pr.index_id WHERE s.database_id = DB_ID() AND i.NAME IS NOT NULL AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0 AND page_count > 100 AND avg_fragmentation_in_percent > 3 AND DB_NAME() = 'DIRECTUM' GROUP BY OBJECT_NAME(s.[object_id]) ,i.NAME ,avg_fragmentation_in_percent ORDER BY avg_fragmentation_in_percent DESC
Состояние выполнения заданий резервного копирования на сервере баз данных СЭД
SELECT d.NAME AS DBName ,MAX(b.backup_finish_date) AS LastBackupCompleted ,DATEDIFF(DAY, MAX(b.backup_finish_date), GETDATE()) AS DurationBackup ,CASE WHEN DATEDIFF(DAY, MAX(b.backup_finish_date), GETDATE()) <= 1 THEN 'OK' WHEN DATEDIFF(DAY, MAX(b.backup_finish_date), GETDATE()) = 2 THEN 'WARNING' WHEN DATEDIFF(DAY, MAX(b.backup_finish_date), GETDATE()) >= 3 THEN 'ALERT' END AS MessageBox FROM sys.databases d LEFT OUTER JOIN msdb..backupset b ON b.database_name = d.NAME AND b.[type] = 'D' WHERE d.NAME NOT IN ( 'master' ,'model' ,'msdb' ,'tempdb' ,'tempbd' ) GROUP BY d.NAME ORDER BY d.NAME
Статистика ожиданий в базе данных СЭД
WITH [Waits] AS ( SELECT [wait_type] ,[wait_time_ms] / 1000.0 AS [WaitS] ,([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS] ,[signal_wait_time_ms] / 1000.0 AS [SignalS] ,[waiting_tasks_count] AS [WaitCount] ,100.0 * [wait_time_ms] / SUM([wait_time_ms]) OVER () AS [Percentage] ,ROW_NUMBER() OVER ( ORDER BY [wait_time_ms] DESC ) AS [RowNum] FROM sys.dm_os_wait_stats WHERE [wait_type] NOT IN ( N'BROKER_EVENTHANDLER' ,N'BROKER_RECEIVE_WAITFOR' ,N'BROKER_TASK_STOP' ,N'BROKER_TO_FLUSH' ,N'BROKER_TRANSMITTER' ,N'CHECKPOINT_QUEUE' ,N'CHKPT' ,N'CLR_AUTO_EVENT' ,N'CLR_MANUAL_EVENT' ,N'CLR_SEMAPHORE' ,N'DBMIRROR_DBM_EVENT' ,N'DBMIRROR_EVENTS_QUEUE' ,N'DBMIRROR_WORKER_QUEUE' ,N'DBMIRRORING_CMD' ,N'DIRTY_PAGE_POLL' ,N'DISPATCHER_QUEUE_SEMAPHORE' ,N'EXECSYNC' ,N'FSAGENT' ,N'FT_IFTS_SCHEDULER_IDLE_WAIT' ,N'FT_IFTSHC_MUTEX' ,N'HADR_CLUSAPI_CALL' ,N'HADR_FILESTREAM_IOMGR_IOCOMPLETION' ,N'HADR_LOGCAPTURE_WAIT' ,N'HADR_NOTIFICATION_DEQUEUE' ,N'HADR_TIMER_TASK' ,N'HADR_WORK_QUEUE' ,N'KSOURCE_WAKEUP' ,N'LAZYWRITER_SLEEP' ,N'LOGMGR_QUEUE' ,N'ONDEMAND_TASK_QUEUE' ,N'PWAIT_ALL_COMPONENTS_INITIALIZED' ,N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP' ,N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP' ,N'REQUEST_FOR_DEADLOCK_SEARCH' ,N'RESOURCE_QUEUE' ,N'SERVER_IDLE_CHECK' ,N'SLEEP_BPOOL_FLUSH' ,N'SLEEP_DBSTARTUP' ,N'SLEEP_DCOMSTARTUP' ,N'SLEEP_MASTERDBREADY' ,N'SLEEP_MASTERMDREADY' ,N'SLEEP_MASTERUPGRADED' ,N'SLEEP_MSDBSTARTUP' ,N'SLEEP_SYSTEMTASK' ,N'SLEEP_TASK' ,N'SLEEP_TEMPDBSTARTUP' ,N'SNI_HTTP_ACCEPT' ,N'SP_SERVER_DIAGNOSTICS_SLEEP' ,N'SQLTRACE_BUFFER_FLUSH' ,N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP' ,N'SQLTRACE_WAIT_ENTRIES' ,N'WAIT_FOR_RESULTS' ,N'WAITFOR' ,N'WAITFOR_TASKSHUTDOWN' ,N'WAIT_XTP_HOST_WAIT' ,N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG' ,N'WAIT_XTP_CKPT_CLOSE' ,N'XE_DISPATCHER_JOIN' ,N'XE_DISPATCHER_WAIT' ,N'XE_TIMER_EVENT' ,N'BACKUPBUFFER' ,N'BACKUPIO' ) ) SELECT TOP 5 [W1].[wait_type] AS [WaitType] ,CAST([W1].[WaitS] AS DECIMAL(16, 2)) AS [Wait_S] ,CAST([W1].[ResourceS] AS DECIMAL(16, 2)) AS [Resource_S] ,CAST([W1].[SignalS] AS DECIMAL(16, 2)) AS [Signal_S] ,[W1].[WaitCount] AS [WaitCount] ,CAST([W1].[Percentage] AS DECIMAL(5, 2)) AS [Percentage] ,CAST(([W1].[WaitS] / [W1].[WaitCount]) AS DECIMAL(16, 4)) AS [AvgWait_S] ,CAST(([W1].[ResourceS] / [W1].[WaitCount]) AS DECIMAL(16, 4)) AS [AvgRes_S] ,CAST(([W1].[SignalS] / [W1].[WaitCount]) AS DECIMAL(16, 4)) AS [AvgSig_S] FROM [Waits] AS [W1] INNER JOIN [Waits] AS [W2] ON [W2].[RowNum] <= [W1].[RowNum] GROUP BY [W1].[RowNum] ,[W1].[wait_type] ,[W1].[WaitS] ,[W1].[ResourceS] ,[W1].[SignalS] ,[W1].[WaitCount] ,[W1].[Percentage] HAVING SUM([W2].[Percentage]) - [W1].[Percentage] < 95
Средняя длительность операций чтения и записи для баз данных сервера
SELECT cast(db_name(a.database_id) AS VARCHAR) AS Database_Name ,b.physical_name ,a.size_on_disk_bytes ,a.io_stall_read_ms / a.num_of_reads 'Средняя задержка одной операции чтения' ,a.io_stall_write_ms / a.num_of_writes 'Средняя задержка одной операции записи' FROM sys.dm_io_virtual_file_stats(NULL, NULL) a INNER JOIN sys.master_files b ON a.database_id = b.database_id AND a.file_id = b.file_id WHERE num_of_writes > 0 AND num_of_reads > 0 ORDER BY Database_Name ,a.io_stall DESC
Таким образом, можем получить следующий вариант информационной панели для серверной части СЭД:
N.B.: Отмечаем, что представленные запросы во многом являются типовыми и не претендуя на уникальность являются в данном контексте лишь демонстрацией возможностей инструментария SSRS применительно к СЭД Directum.
Для вывода показателей клиентского рабочего места СЭД может быть использован следующий набор данных:
Количество объектов в папках
SELECT SBFolder.NAME AS FolderName ,COUNT(SBFolder.NAME) AS CountObject ,SBFolder.ShowUnread FROM SBLinks INNER JOIN SBFolder ON SBLinks.SourceID = SBFolder.XRecID INNER JOIN MBAnalit ON SBFolder.Author = MBAnalit.Analit WHERE MBAnalit.Dop = @User AND SBFolder.FolderType IN ( 'P' ,'I' ,'O' ,'F' ) GROUP BY SBFolder.NAME ,SBFolder.ShowUnread
Просмотры заданий
SELECT CASE WHEN SBTaskJob.Readed = 'Y' THEN 'Readed' WHEN SBTaskJob.Readed = 'N' THEN 'Not readed' END AS STATE ,COUNT(Readed) AS IsReaded FROM SBTaskJob INNER JOIN MBAnalit ON SBTaskJob.Executor = MBAnalit.Analit WHERE MBAnalit.Dop = @User GROUP BY Readed
Задачи со сроками исполнения
WITH t1 (CountFailedNow) AS ( SELECT COUNT(STATE) AS CountFailedNow FROM SBTaskJob INNER JOIN MBAnalit ON SBTaskJob.Executor = MBAnalit.Analit WHERE MBAnalit.Dop = @User AND Kind != 'N' AND FinalDate <= GETDATE() AND STATE = 'W' ) ,t2 (CountTask) AS ( SELECT COUNT(STATE) AS CountTask FROM SBTaskJob INNER JOIN MBAnalit ON SBTaskJob.Executor = MBAnalit.Analit WHERE MBAnalit.Dop = @User AND Kind != 'N' AND FinalDate IS NOT NULL AND STATE != 'W' AND FinalDate <= EndDate ) ,t3 (CompleteFailedFullTime) AS ( SELECT COUNT(STATE) AS CompleteFailedFullTime FROM SBTaskJob INNER JOIN MBAnalit ON SBTaskJob.Executor = MBAnalit.Analit WHERE MBAnalit.Dop = @User AND Kind != 'N' AND FinalDate > EndDate AND STATE != 'W' ) SELECT 'Execute' AS CName ,CountTask ,CompleteFailedFullTime ,CountFailedNow FROM t1 ,t2 ,t3
Исполнение заданий
SELECT CASE WHEN SBTaskJob.STATE = 'W' THEN 'Work' WHEN SBTaskJob.STATE = 'D' THEN 'Complete' WHEN SBTaskJob.STATE = 'B' THEN 'Stop' END AS STATE ,COUNT(STATE) AS CountState FROM SBTaskJob INNER JOIN MBAnalit ON SBTaskJob.Executor = MBAnalit.Analit WHERE MBAnalit.Dop = @User AND Kind != 'N' GROUP BY STATE
При построении элементов отчета, применимых к отдельному пользователю, нами был использован параметр User, имеющий динамическое значение по умолчанию. Данный параметр задает имя пользователя, для которого строится отчет и его содержанием является значение логина пользователя, который обращается к серверу SSRS (User!UserID). Это же значение, в нашем случае, является и логином пользователя в СЭД. Наиболее удобно добавлять ссылку на подобный отчет в качестве обложки папки в СЭД:
Пользователь, запустивший отчет, видит только данные, отфильтрованные для своей учетной записи.
Для создания элемента отчета с автоматическим анализом объектов СЭД нами были использованы свойства этих элементов, позволяющие задавать их значение на основе заданных выражений:
Выражение ячейки Tablix для генерирования рекомендации по настройке свойств
IIf(Fields!ShowUnread.Value="Y", "Отображение этой папки в списке замедляет работы системы. Для ускорения работы СЭД DIRECTUM рекомендуем отключить вывод количества непрочитанных сообщений", "OK")
Выражение ячейки Tablix для генерирования рекомендации по настройке содержания
IIf(Fields!CountObject.Value>100, "Открытие этой папки значительно снижает производительность системы. Для ускорения работы СЭД DIRECTUM необходимо уменьшить количество ссылок до максимально допустимого (до 100 ссылок)", IIf(Fields!CountObject.Value>80, "Открытие этой папки несколько замедляет работу системы. Для ускорения работы СЭД DIRECTUM необходимо уменьшить количество ссылок до рекомендуемого (до 80 ссылок)", "OK"))
Наблюдение за показателями производительности системы будет полезно технической поддержке и администраторам СЭД, а эффективность использования СЭД может оказаться полезной как при анализе и оптимизации бизнес-процессов, так и в случае оценки качества работы сотрудников:
Таким образом, количество и качество выводимых показателей, а также компоновка данных и как следствие – эффективность созданной информационной панели ограничивается возможностями сервера базы данных СЭД и потребностями пользователей.
Подробную информацию о перечисленных компонентах SSRS можно найти в библиотеке MSDN:
А где взять сам отчет из примера? :)
Который из трех представленных?
Тогда все три :)
Просто БОМБА!!!
Код для двух отчетов из трех на 90% приведен в примерах. Если все-таки хочется готовые RDL-ки, пишите.
Мастхэв всем!
Спасибо!
В User!UserID у меня доменный юзер сидит, а как передать SQL-ного?
Это не исключение. Подробнее см. статью в библиотеке MSDN: https://msdn.microsoft.com/en-us/library/dd255216.aspx?f=255&MSPPError=-2147217396
Как вариант - задействовать Forms-авторизацию SSRS, чтобы сервер отчетов получил пользователя SQL. SSRS поддерживает Forms, подробнее см. статью в библиотеке MSDN: https://msdn.microsoft.com/en-us/library/ms160724(v=SQL.120).aspx
Авторизуйтесь, чтобы написать комментарий